《剑指offer》算法题第七天

今日题目:

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

 

1.复杂链表的复制

题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路:
这道题比较简单的做法是利用哈希表,把旧节点当成key,把新节点当成value,然后再来建立关系,时间和空间复杂度均为O(n)
另外一种做法是将新生成的节点插入旧节点之间,然后再进行提取,时间复杂度为O(n),空间复杂度为O(1)。

代码如下:

 1 //利用HashMap
 2 public class Solution {
 3     public RandomListNode Clone(RandomListNode pHead)
 4     {
 5         if(pHead == null) return null;
 6         Map<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
 7         RandomListNode p = pHead;
 8         while(p != null){
 9             map.put(p,new RandomListNode(p.label));
10             p = p.next;
11         }
12         p = pHead;
13         while(p != null){
14             RandomListNode new_node = map.get(p);
15             if(p.next != null)
16                 new_node.next = map.get(p.next);
17             if(p.random != null)
18                 new_node.random = map.get(p.random);
19             p = p.next;
20         }
21         return map.get(pHead);
22     }
23 }
24 
25 
26 //没用到HashMap
27 public class Solution {
28     public RandomListNode Clone(RandomListNode pHead)
29     {
30         if(pHead == null) return null;
31         RandomListNode p = pHead;
32         while(p != null){
33             RandomListNode next = p.next;
34             p.next = new RandomListNode(p.label);
35             p.next.next = next;
36             p = next;
37         }
38          
39         p = pHead;
40         while(p != null){
41             if(p.random != null)
42                 p.next.random = p.random.next;
43             p = p.next.next;
44         }
45          
46         RandomListNode dummy = new RandomListNode(0);
47         RandomListNode q = dummy;
48         p = pHead;
49         while(p != null){
50             RandomListNode tmp = p.next.next;
51             q.next = p.next;
52             q = q.next;
53              
54             p.next = tmp;
55              
56             p = tmp;
57         }
58          
59         return dummy.next;
60     }
61 }

 

 

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

题目描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

思路:
这道题利用二叉搜索树中序遍历序列递增的特性来求解,比较直接。

代码如下:

 1 public class Solution {
 2     public TreeNode Convert(TreeNode root) {
 3         if(root == null) return null;
 4         Stack<TreeNode> stack = new Stack();
 5         boolean flag = true;
 6         TreeNode p = root;
 7         TreeNode pre = null;
 8         while(p != null || !stack.empty()){
 9             if(p != null){
10                 stack.push(p);
11                 p = p.left;
12             }else{
13                 TreeNode node = stack.pop();
14                 if(flag){
15                     root = node;
16                     flag = false;
17                 }
18                 if(pre != null)
19                     pre.right = node;
20                 node.left = pre;
21                 pre = node;
22                 p = node.right;
23             }
24         }
25         return root;
26         
27     }
28 }

 

 

3. 序列化二叉树

题目描述:
请实现两个函数,分别用来序列化和反序列化二叉树

思路:
序列化:比较直接,先序遍历二叉树来生成序列
反序列化:也是根据先序遍历的思想来做的,但是可能比起序列化来说没那么直观。

代码如下:

 1 public class Solution {
 2     int index = -1;
 3     String Serialize(TreeNode root) {
 4         StringBuffer sb = new StringBuffer();
 5         if(root == null){
 6             sb.append("#,");
 7             return sb.toString();
 8         }
 9         sb.append(root.val+",");
10         sb.append(Serialize(root.left));
11         sb.append(Serialize(root.right));
12         return sb.toString();
13   }
14     TreeNode Deserialize(String str) {
15         index++;
16        int len = str.length();
17         if(index >= len){
18             return null;
19         }
20         String[] strr = str.split(",");
21         TreeNode node = null;
22         if(!strr[index].equals("#")){
23             node = new TreeNode(Integer.valueOf(strr[index]));
24             node.left = Deserialize(str);
25             node.right = Deserialize(str);
26         }
27          
28         return node;
29   }
30 }

 

4. 字符串的排列

题目描述:
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

思路:
回溯法的题目做多了这道题就不是什么难事,唯一要注意的是字符串中的字符有可能是有重复的。
参考答案给了另外一种基于交换的解法,比博主自己写的回溯要好得多,下面贴出代码给大家参考。

代码如下:

 1 //博主写的回溯法
 2 public class Solution {
 3     public ArrayList<String> Permutation(String str) {
 4         ArrayList<String> res = new ArrayList();
 5         if(str.length() == 0) return res;
 6         char[] arr = str.toCharArray();
 7         Arrays.sort(arr);
 8         backtrack(arr,res,new StringBuffer(),new HashSet());
 9         return res;
10     }
11      
12     public void backtrack(char[] arr,ArrayList<String> res,StringBuffer sb,HashSet<Integer> visited){
13         if(sb.length() == arr.length){
14             res.add(sb.toString());
15             return;
16         }
17         for(int i = 0; i < arr.length; i++){
18             if(visited.contains(i)) continue;
19             sb.append(arr[i]);
20             visited.add(i);
21             backtrack(arr,res,sb,visited);
22             visited.remove(i);
23             sb.deleteCharAt(sb.length()-1);
24             while(i < arr.length-1 && arr[i] == arr[i+1]) i++;
25         }
26     }
27 }
28 
29 
30 //参考答案给的方法,强烈推荐!!
31 public class Solution {
32     public ArrayList<String> Permutation(String str) {
33         ArrayList<String> res = new ArrayList();
34         if(str.length() == 0) return res;
35         char[] arr = str.toCharArray();
36         backtrack(arr,res,0);
37         Collections.sort(res);
38         return res;
39     }
40      
41     public void backtrack(char[] arr,ArrayList<String> res,int ind){
42         if(ind == arr.length-1){
43             res.add(String.valueOf(arr));
44             return;
45         }
46         for(int i = ind; i < arr.length; i++){
47             if(i != ind && arr[i] == arr[ind]) continue;
48             char swap = arr[ind];
49             arr[ind] = arr[i];
50             arr[i] = swap;
51              
52             backtrack(arr,res,ind+1);
53              
54             swap = arr[ind];
55             arr[ind] = arr[i];
56             arr[i] = swap;
57         }
58     }
59 }

 

posted @ 2018-02-03 16:24  wezheng  阅读(175)  评论(0编辑  收藏  举报