Leetcode: 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.

难度70,与Convert Sorted Array to Binary Search Tree问题相似,这道题的做法就是,我们需要中点来做每一层树的根,问题在于,对于一个链表我们是不能常量时间访问它的中间元素的。于是我的想法是花O(N)的时间把链表里面的元素先存到一个数组或者ArrayList里面,这样就有了一个sorted的数组或者ArrayList,我们就很容易对它递归来建立一个height balanced BST

 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     public TreeNode sortedListToBST(ListNode head) {

20         if (head == null) return null;

21         ListNode dummy = new ListNode(-1);

22         dummy.next = head;

23         ListNode cursor = dummy;

24         int count = 0;

25         while (cursor.next != null) {

26             count++;

27             cursor = cursor.next;

28         }

29         int[] array = new int[count];

30         cursor = dummy;

31         for (int i = 0; i < count; i++) {

32             array[i] = cursor.next.val;

33             cursor = cursor.next;

34         }

35         TreeNode result = helper(array, 0, array.length - 1);

36         return result;

37     }

38     

39     public TreeNode helper(int[] array, int begin, int end) {

40         if (begin > end) return null;42         int mid = (begin + end) / 2;

43         TreeNode root = new TreeNode(array[mid]);

44         root.left = helper(array, begin, mid - 1);

45         root.right = helper(array, mid + 1, end);

46         return root;

47     }

48 }

用ArrayList的做法:

 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     public TreeNode sortedListToBST(ListNode head) {

20         if (head == null) return null;

21         

22         ArrayList<Integer> listNode = new ArrayList<Integer>();

23         while(head != null){

24             listNode.add(head.val);

25             head = head.next;

26         }

27         int left = 0;

28         int right= listNode.size()-1;

29         return helper(listNode, left, right);

30     }

31     

32     public TreeNode helper(ArrayList<Integer> listNode, int left, int right){

33         if(left>right) return null;

34         

35         TreeNode node = new TreeNode(0);

36         int mid = (left+right)/2;

37         node.val = listNode.get(mid);

38         node.left = helper(listNode, left, mid-1);

39         node.right = helper(listNode, mid+1, right);            

40         return node;

41     }

42 }

 Code Ganker有一个做法,整体过程就是一次中序遍历,时间复杂度是O(n),空间复杂度是栈空间O(logn)加上结果的空间O(n),额外空间是O(logn),总体是O(n)。代码如下:我的额外空间是O(N),他的做法比我优。

他的做法精髓在于:1. helper函数里递归实现了树的inorder访问,ArrayList<ListNode> list中list.get(0).val存的就是当前树inorder遍历正遍历到的节点其value值。我们依次把LinkedList里面的节点挨个添加到list.get(0),由于LinkedList是sorted的,所以LinkedList里面的点与BST inorder遍历的各个点是一一对应的,我们只需要用当前LinkedList节点的val去创建BST当前的节点就好了。

2. helper函数的 int l, int r看似不影响中序遍历,但是却帮助我们判断什么时候当前节点是null,作用就跟中序遍历递归写法里面的判空语句 if(root == null)return; 一样

 1 public TreeNode sortedListToBST(ListNode head) {

 2     if(head == null)

 3         return null;

 4     ListNode cur = head;

 5     int count = 0;

 6     while(cur!=null)

 7     {

 8         cur = cur.next;

 9         count++;

10     }

11     ArrayList<ListNode> list = new ArrayList<ListNode>();

12     list.add(head);

13     return helper(list,0,count-1);

14 }

15 private TreeNode helper(ArrayList<ListNode> list, int l, int r)

16 {

17     if(l>r)

18         return null;

19     int m = (l+r)/2;

20     TreeNode left = helper(list,l,m-1);

21     TreeNode root = new TreeNode(list.get(0).val);

22     root.left = left;

23     list.set(0,list.get(0).next);

24     root.right = helper(list,m+1,r);

25     return root;

26 }

 注意这个代码里面11行-12行,为什么要用一个ArrayList来装载ListNode head再以这个ArrayList作为参数参与递归?这是一个很好的java函数参数问题。如果直接用ListNode head作为参数参与递归,代码如下,这样做是会报错的。原因已经写在《Summary: Java中函数参数的传递》这篇博文里面,这个情况就是里面描述的“(二)对象类型参数:传引用,方法体内改变形参引用,不会改变实参的引用”。在下面代码的22行“node = node.next;” 这里形参引用ListNode node发生了改变, 指向下一个,但是调用它的外层helper函数中的实参ListNode node没有发生任何变化,并没有指向下一个。要想让外层函数的node变化,一个方法是:把node放在ArrayList的index 0处,每次修改index 0的内容,传递ArrayList,这样实参也变化了。

 1 public class Solution {

 2     public TreeNode sortedListToBST(ListNode head) {

 3         if(head == null)

 4             return null;

 5         ListNode cur = head;

 6         int count = 0;

 7         while(cur!=null)

 8         {

 9             cur = cur.next;

10             count++;

11         }

12         return helper(head,0,count-1);

13     }

14     private TreeNode helper(ListNode node, int l, int r)

15     {

16         if(l>r)

17             return null;

18         int m = (l+r)/2;

19         TreeNode left = helper(node,l,m-1);

20         TreeNode root = new TreeNode(node.val);

21         root.left = left;

22         node = node.next;

23         root.right = helper(node,m+1,r);

24         return root;

25     }

26 }

 

你可能感兴趣的:(Binary search)