• 《剑指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 }
  • 相关阅读:
    Linux基础学习(7)
    Linux基础学习(6)
    Linux基础学习(5)
    Linux基础学习(4)
    Linux基础学习(3)
    测试工程师面试题
    Postman实战
    接口测试
    HTTP请求结构与HTTP响应结构
    GET请求与POST请求的区别
  • 原文地址:https://www.cnblogs.com/wezheng/p/8409809.html
Copyright © 2020-2023  润新知