109. Convert Sorted List to Binary Search Tree
该题需要用一个递增的链表构建一个二叉树。数组的中位数为数的根节点,以中位数为分界,可以将数组分成左子数组以及右子数组,那么左边数组的中位数是左节点的值,右边数组的中位数为右节点的值,以此类推。
所以我们可以想到,首先需要将链表转换为数组,然后直接定位中位数的值为根节点的值,并通过递归的方法分别构造左子树以及右子树。
代码如下:
1 /**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 * int val;
5 * ListNode next;
6 * ListNode(int x) { val = x; }
7 * }
8 */
9 /**
10 * Definition for a binary tree node.
11 * public class TreeNode {
12 * int val;
13 * TreeNode left;
14 * TreeNode right;
15 * TreeNode(int x) { val = x; }
16 * }
17 */
18 class Solution {
19 public TreeNode sortedListToBST(ListNode head) {
20 if(head == null){
21 return null;
22 }
23
24 ListNode temp = head;
25 int nodenum = 0;
26 while(temp != null){
27 temp = temp.next;
28 nodenum ++;
29 }
30
31 int[] temparray = new int[nodenum];
32 temp = head;
33
34 for(int i = 0 ; i < nodenum ; i++){
35 temparray[i] = temp.val;
36 temp = temp.next;
37 }
38
39 TreeNode root = new TreeNode(0);
40 helper(root, temparray, 0, nodenum - 1);
41
42 return root;
43 }
44
45 private void helper(TreeNode res, int[] arr, int lindex, int rindex){
46
47 int pos = (rindex - lindex + 1)%2 == 0 ? (rindex + lindex + 1)/2:(rindex + lindex)/2;
48 res.val = arr[pos];
49
50 if(pos - 1 >= lindex){
51 res.left = new TreeNode(0);
52 helper(res.left, arr, lindex, pos - 1);
53 }
54
55 if( rindex >= pos + 1){
56 res.right = new TreeNode(0);
57 helper(res.right, arr, pos + 1, rindex);
58 }
59 }
60 }
怎么才能不需要额外空间就能够实现二叉树的构建呢?参考了一下以下链接,
https://blog.csdn.net/worldwindjp/article/details/39722643
分别有自顶向下以及自底向上的构建方法。
贴上方法一的代码:
1 public class Solution {
2 ListNode getLeftNodeFromList(ListNode head) {
3 ListNode next = head;
4 ListNode current = head;
5 ListNode pre = head;
6
7 while(next!=null) {
8 next = next.next;
9 if(next==null) {
10 break;
11 }
12 next = next.next;
13 if(next==null) {
14 break;
15 }
16 pre = head;
17 head = head.next;
18 }
19 return pre;
20 }
21
22
23 public TreeNode sortedListToBST(ListNode head) {
24 if(head==null) {
25 return null;
26 }
27 if(head.next==null) {
28 return new TreeNode(head.val);
29 }
30
31 ListNode left = getLeftNodeFromList(head);
32 ListNode mid = left.next;
33 TreeNode root = new TreeNode(mid.val);
34 left.next = null;
35 root.left = sortedListToBST(head);
36 root.right = sortedListToBST(mid.next);
37 return root;
38 }
39 }
不需要额外空间的关键在于能够找到在链表当中获取中位数的方法,主要思路为定义了两个指针,在遍历链表的时候,一个指针每次循环遍历两个节点,一个只是遍历一个,当遍历两个的指针为空的时候,另一个指针就会指向链表的中间节点。
利用这种思路,首先找出链表中中间节点的前一个节点,然后使用中间节点的值构造根节点;接着将链表分拆成左边的链表以及右边的链表,中间节点的前一个节点的next定义为null,那么中间节点的next就指向了右边的链表,以此类推。
贴上方法二的代码:
1 public class Solution {
2 static ListNode currentHead = null;
3 TreeNode buildTree(int start, int end) {
4 if(start>end) {
5 return null;
6 }
7 int mid = start + (end - start)/2;
8 TreeNode left = buildTree(start, mid-1);
9 TreeNode root = new TreeNode(currentHead.val);
10 root.left = left;
11 currentHead = currentHead.next;
12 root.right = buildTree(mid + 1, end);
13 return root;
14 }
15
16 public TreeNode sortedListToBST(ListNode head) {
17 if(head==null) {
18 return null;
19 }
20 currentHead = head;
21 int len = 0;
22 while(head!=null) {
23 len++;
24 head = head.next;
25 }
26
27 return buildTree(0, len-1);
28 }
29 }
方法二是先构造左子树,通过递归,首先找出链表第一个节点在树中的位置,找到后用链表节点的值构造树节点,接着寻找链表第二个节点在树中的位置,以此类推。
END