今日题目:

  1. 复杂链表的复制
  2. 二叉搜索树与双向链表
  3. 序列化二叉树
  4. 字符串的排序

1.复杂链表的复制

题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空) 思路:
这道题比较简单的做法是利用哈希表,把旧节点当成key,把新节点当成value,然后再来建立关系,时间和空间复杂度均为O(n)
另外一种做法是将新生成的节点插入旧节点之间,然后再进行提取,时间复杂度为O(n),空间复杂度为O(1)。

代码如下:

 //利用HashMap
public class Solution {
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead == null) return null;
Map<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
RandomListNode p = pHead;
while(p != null){
map.put(p,new RandomListNode(p.label));
p = p.next;
}
p = pHead;
while(p != null){
RandomListNode new_node = map.get(p);
if(p.next != null)
new_node.next = map.get(p.next);
if(p.random != null)
new_node.random = map.get(p.random);
p = p.next;
}
return map.get(pHead);
}
} //没用到HashMap
public class Solution {
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead == null) return null;
RandomListNode p = pHead;
while(p != null){
RandomListNode next = p.next;
p.next = new RandomListNode(p.label);
p.next.next = next;
p = next;
} p = pHead;
while(p != null){
if(p.random != null)
p.next.random = p.random.next;
p = p.next.next;
} RandomListNode dummy = new RandomListNode(0);
RandomListNode q = dummy;
p = pHead;
while(p != null){
RandomListNode tmp = p.next.next;
q.next = p.next;
q = q.next; p.next = tmp; p = tmp;
} return dummy.next;
}
}

2. 二叉搜索树与双向链表

题目描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。 思路:
这道题利用二叉搜索树中序遍历序列递增的特性来求解,比较直接。

代码如下:

 public class Solution {
public TreeNode Convert(TreeNode root) {
if(root == null) return null;
Stack<TreeNode> stack = new Stack();
boolean flag = true;
TreeNode p = root;
TreeNode pre = null;
while(p != null || !stack.empty()){
if(p != null){
stack.push(p);
p = p.left;
}else{
TreeNode node = stack.pop();
if(flag){
root = node;
flag = false;
}
if(pre != null)
pre.right = node;
node.left = pre;
pre = node;
p = node.right;
}
}
return root; }
}

3. 序列化二叉树

题目描述:
请实现两个函数,分别用来序列化和反序列化二叉树 思路:
序列化:比较直接,先序遍历二叉树来生成序列
反序列化:也是根据先序遍历的思想来做的,但是可能比起序列化来说没那么直观。

代码如下:

 public class Solution {
int index = -1;
String Serialize(TreeNode root) {
StringBuffer sb = new StringBuffer();
if(root == null){
sb.append("#,");
return sb.toString();
}
sb.append(root.val+",");
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
TreeNode Deserialize(String str) {
index++;
int len = str.length();
if(index >= len){
return null;
}
String[] strr = str.split(",");
TreeNode node = null;
if(!strr[index].equals("#")){
node = new TreeNode(Integer.valueOf(strr[index]));
node.left = Deserialize(str);
node.right = Deserialize(str);
} return node;
}
}

4. 字符串的排列

题目描述:
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 思路:
回溯法的题目做多了这道题就不是什么难事,唯一要注意的是字符串中的字符有可能是有重复的。
参考答案给了另外一种基于交换的解法,比博主自己写的回溯要好得多,下面贴出代码给大家参考。

代码如下:

 //博主写的回溯法
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> res = new ArrayList();
if(str.length() == 0) return res;
char[] arr = str.toCharArray();
Arrays.sort(arr);
backtrack(arr,res,new StringBuffer(),new HashSet());
return res;
} public void backtrack(char[] arr,ArrayList<String> res,StringBuffer sb,HashSet<Integer> visited){
if(sb.length() == arr.length){
res.add(sb.toString());
return;
}
for(int i = 0; i < arr.length; i++){
if(visited.contains(i)) continue;
sb.append(arr[i]);
visited.add(i);
backtrack(arr,res,sb,visited);
visited.remove(i);
sb.deleteCharAt(sb.length()-1);
while(i < arr.length-1 && arr[i] == arr[i+1]) i++;
}
}
} //参考答案给的方法,强烈推荐!!
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> res = new ArrayList();
if(str.length() == 0) return res;
char[] arr = str.toCharArray();
backtrack(arr,res,0);
Collections.sort(res);
return res;
} public void backtrack(char[] arr,ArrayList<String> res,int ind){
if(ind == arr.length-1){
res.add(String.valueOf(arr));
return;
}
for(int i = ind; i < arr.length; i++){
if(i != ind && arr[i] == arr[ind]) continue;
char swap = arr[ind];
arr[ind] = arr[i];
arr[i] = swap; backtrack(arr,res,ind+1); swap = arr[ind];
arr[ind] = arr[i];
arr[i] = swap;
}
}
}

《剑指offer》算法题第七天的更多相关文章

  1. 剑指offer算法题

    数组中只出现一次的数字(一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字): 解法在于位运算中的异或,直接异或可以得到这两个数的异或,按照最后的有效数字位可以 ...

  2. 剑指offer算法总结

    剑指offer算法学习总结 节选剑指offer比较经典和巧妙的一些题目,以便复习使用.一部分题目给出了完整代码,一部分题目比较简单直接给出思路.但是不保证我说的思路都是正确的,个人对算法也不是特别在行 ...

  3. 剑指Offer——算法复杂度中的O(logN)底数是多少

    剑指Offer--算法复杂度中的O(logN)底数是多少 前言 无论是计算机算法概论.还是数据结构书中,关于算法的时间复杂度很多都用包含O(logN)这样的描述,但是却没有明确说logN的底数究竟是多 ...

  4. 剑指 offer 第一题: 二维数组中的查找

    打算写 图解剑指 offer 66 题 的系列文章,不知道大家有没有兴趣

  5. 剑指Offer编程题2——替换空格

    剑指Offer编程题2——替换空格 题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happ ...

  6. 剑指Offer编程题1——二维数组中的查找

    剑指Offer编程题1---------------二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完 ...

  7. 剑指offer编程题66道题 36-66

    36.两个链表的第一个公共节点 题目描述 输入两个链表,找出它们的第一个公共结点. 1.具有重合节点的两个链表是一个Y字性,用两个堆栈放这两个链表,从尾部开始遍历,直到遍历到最后一个重合节点. 这种算 ...

  8. 牛客网剑指offer刷题总结

    二维数组中的查找: 题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 两 ...

  9. LeetCode剑指Offer刷题总结(一)

    LeetCode过程中值得反思的细节 以下题号均指LeetCode剑指offer题库中的题号 本文章将每周定期更新,当内容达到10题左右时将会开下一节. 二维数组越界问题04 public stati ...

  10. 剑指offer编程题Java实现——面试题11数值的整数次方

    题目: 实现函数double power(double base,int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 解题思路:最一般的方法实现数值 ...

随机推荐

  1. 26-Perl 包和模块

    1.Perl 包和模块Perl 中每个包有一个单独的符号表,定义语法为:package mypack;此语句定义一个名为 mypack 的包,在此后定义的所有变量和子程序的名字都存贮在该包关联的符号表 ...

  2. 《深入实践C++模板编程》之三——模板参数类型详解

    非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板.   1.整 ...

  3. C#面向对象21 接口

    接口的规范: 1.接口是一种规范.只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员. 2.为了多态,接口不能被实例化,接口不new(不能创建对象) 3.接口中的成员不能加“访问修饰符”, ...

  4. 查找和杀掉占用GPU显存的进程

    用只有2个G的显卡跑数据就需要在训练之前先把无关进程杀掉,防止跑到一半显存满了 nvidia-smi:显示当前GPU中的线程 kill -9 PID:输入PID以结束线程

  5. Ubuntu12.04+Caffe (+OpenCV+CPU-only)

    经过一天的努力发现12.04 的pcre的库太低了,   要解决这个bug只能升级系统到16.04   麻蛋!!! 1.  下载大神MTCNN 源码,内含caffe https://github.co ...

  6. 实现双向绑定Proxy比defineproperty优劣如何?

    前言 双向绑定其实已经是一个老掉牙的问题了,只要涉及到MVVM框架就不得不谈的知识点,但它毕竟是Vue的三要素之一. Vue三要素 响应式: 例如如何监听数据变化,其中的实现方法就是我们提到的双向绑定 ...

  7. 99乘法表(js)

    //九九乘法表 let i,j,str; for(i=1;i<=9;i++) { str = ""; for(j=1;j<=i;j++) { str = str+i+' ...

  8. powershell查看版本信息

    在终端输入$PSVersionTable

  9. hbuilder打包集成文件预览

    <div class="attachments"> <div class="name">附件</div> <div c ...

  10. dhcpd.conf配置文件几例

    例1   ddns-update-style interim; ignore client-updates; subnet 192.168.222.0 netmask 255.255.255.0 { ...