• LeetCode: Convert Sorted List to Binary Search Tree 解题报告


    Convert Sorted List to Binary Search Tree 

    Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

    Show Tags

    SOLUTION 1:

    这个方法比较暴力,每次遍历当前list,找到中间的节点,建立 root,分别使用递归建立左树以及右树,并将左右树挂在root之下。但这个算法会复杂度很高。
    建立root次数为N,每次遍历最多N次,最坏为N平方(实际不会这么多)
     1 public TreeNode sortedListToBST1(ListNode head) {
     2         ListNode fast = head;
     3         ListNode slow = head;
     4         
     5         ListNode pre = head;
     6         
     7         if (head == null) {
     8             return null;
     9         }
    10         
    11         TreeNode root = null;
    12         if (head.next == null) {
    13             root = new TreeNode(head.val);
    14             root.left = null;
    15             root.right = null;
    16             return root;
    17         }
    18         
    19         // get the middle node.
    20         while (fast != null && fast.next != null) {
    21             fast = fast.next.next;
    22             
    23             // record the node before the SLOW.
    24             pre = slow;
    25             slow = slow.next;
    26         }
    27         
    28         // cut the list to two parts.
    29         pre.next = null;
    30         TreeNode left = sortedListToBST1(head);
    31         TreeNode right = sortedListToBST1(slow.next);
    32         
    33         root = new TreeNode(slow.val);
    34         root.left = left;
    35         root.right = right;
    36         
    37         return root;
    38     }
    View Code

    SOLUTION 2:

     这个解法使用一个参数来记录当前正在操作的List Node. DFS本身的效果是,从head直到尾部建树,并且将currNode移动到size+1处。
    这样可以在1次iterator 我们的List后直接建立树。
    这是一种Bottom-up的建树方法。如果我们使用C++,则可以将List Node的指针直接做为入参。我们这里使用了类似的方法,不过,
    Java不能使用指针,所以我们自建一个自定义的类,里面只有一个ListNode,这样我们就能方便地修改入参了(好纠结啊,这时主页君就开始怀念起C的指针了),
    :)
    C++版本可以参见张磊哥哥的解答喔:)
     1 public TreeNode sortedListToBST(ListNode head) {
     2         if (head == null) {
     3             return null;
     4         }
     5         
     6         int size = 0;
     7         ListNode cur = head;
     8         while (cur != null) {
     9             size++;
    10             cur = cur.next;
    11         }
    12          
    13         CurrNode curNode = new CurrNode(head); 
    14         return sortedListToBSTHelp(curNode, size);
    15     }
    16     
    17     public class CurrNode {
    18         ListNode node;
    19         
    20         CurrNode(ListNode node) {
    21             this.node = node;
    22         }
    23     }
    24     
    25     // when the recursion is done, the curr node should point to the node
    26     // which is the next of the block.
    27     public TreeNode sortedListToBSTHelp(CurrNode curr, int size) {
    28         if (size <= 0) {
    29             return null;
    30         }
    31         
    32         TreeNode left = sortedListToBSTHelp(curr, size/2);
    33         
    34         // because we want to deal with the right block.
    35         TreeNode root = new TreeNode(curr.node.val);
    36         curr.node = curr.node.next;
    37         
    38         TreeNode right = sortedListToBSTHelp(curr, size - 1 - size/2);
    39         
    40         root.left = left;
    41         root.right = right;
    42         
    43         return root;
    44     }
    View Code

    SOLUTION 3:

    这个解法使用一个instance variable 来记录当前正在操作的List Node. DFS本身的效果是,从head直到尾部建树,并且将currNode移动到size+1处。
    这样可以在1次iterator 我们的List后直接建立树。
    这是一种Bottom-up的建树方法。如果我们使用C++,则可以将List Node直接做为入参来改变之而不需要使用实例变量。
    问题是:我们如果可以的话,尽量不要使用实例变量,因为它是各个Method 共享的,所以这个方法存在风险。因为变量有可能被别的方法修改。
     
    这个dfs的意思就是 对一个以head 起始的list, size为大小的list建一个树,一个bfs树
    并且这个dfs有一个作用 会把指针移动到这个要建的树的下一个位置
     
    这样 我们先建立左树,        TreeNode left = dfs(head, size / 2);
    经过这一行 cur就移动到了中间
    我们建立 一个根         TreeNode root = new TreeNode(curNode.val);

    把cur移动到下一个     curNode = curNode.next;
    再用递归建立右树      
     
    构造我们想要的树 返回根结果
    root.left = left;
    root.right = right;
    return root;
     1 /**
     2  * Definition for singly-linked list.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) { val = x; next = null; }
     7  * }
     8  */
     9 /**
    10  * Definition for binary tree
    11  * public class TreeNode {
    12  *     int val;
    13  *     TreeNode left;
    14  *     TreeNode right;
    15  *     TreeNode(int x) { val = x; }
    16  * }
    17  */
    18 public class Solution {
    19     ListNode curNode = null;
    20     
    21     public TreeNode sortedListToBST(ListNode head) {
    22         if (head == null) {
    23             return null;
    24         }
    25         
    26         int size = 0;
    27         ListNode cur = head;
    28         while (cur != null) {
    29             size++;
    30             cur = cur.next;
    31         }
    32         
    33         curNode = head;
    34         return dfs(head, size);
    35     }
    36     
    37     // Use the size to control.
    38     public TreeNode dfs(ListNode head, int size) {
    39         if (size <= 0) {
    40             return null;
    41         }
    42         
    43         TreeNode left = dfs(head, size / 2);
    44         TreeNode root = new TreeNode(curNode.val);
    45         
    46         // move the current node to the next place.
    47         curNode = curNode.next;
    48         TreeNode right = dfs(curNode, size - size / 2 - 1);
    49         
    50         root.left = left;
    51         root.right = right;
    52         
    53         return root;
    54     }
    55 }
    View Code
  • 相关阅读:
    win10没有新建文件夹
    js暂停的函数
    Mini ORM——PetaPoco笔记
    阻止网页内部滚动条mousewheel事件冒泡
    setTimeout调用带参数的函数的方法
    spring入门--Spring框架底层原理
    spring入门——applicationContext与BeanFactory的区别
    mybatis的Sql语句打印
    Sql语句中IN和exists的区别及应用
    Jenkins学习
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4392084.html
Copyright © 2020-2023  润新知