Nameless Site

But one day, you will stand before its decrepit gate,without really knowing why.

0%

有序链表转化二叉搜索树

来源Leetcode第109题有序链表转化二叉搜索树

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

1
2
3
4
5
6
7
8
9
给定的有序链表: [-10, -3, 0, 5, 9],

一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:

0
/ \
-3 9
/ /
-10 5

链表转数组

将链表转化成数组,在套用第108题的代码即可,注意在Arrays.copyOfRange()方法中,复制的区间是左闭又开,即[left,right),所以右侧区间要+1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public TreeNode sortedArrayToBST(Integer[] nums) {
if(nums.length == 0 || nums == null)
return null;
int mid = nums.length / 2;
TreeNode root = new TreeNode(nums[mid]);
if(mid > 0)
root.left = sortedArrayToBST(Arrays.copyOfRange(nums,0,mid));
if(mid < nums.length - 1)
root.right = sortedArrayToBST(Arrays.copyOfRange(nums,mid + 1,nums.length));
return root;
}

public TreeNode sortedListToBST(ListNode head) {
List<Integer> num = new ArrayList<>();
while(head != null){
num.add(head.val);
head = head.next;
}
//System.out.println();
Integer[] nums = num.toArray(new Integer[num.size()]);
return sortedArrayToBST(nums);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* Definition for singly-linked list. public class ListNode { int val; ListNode next; ListNode(int
* x) { val = x; } }
*/
/**
* Definition for a binary tree node. public class TreeNode { int val; TreeNode left; TreeNode
* right; TreeNode(int x) { val = x; } }
*/
class Solution {

private List<Integer> values;

public Solution() {
this.values = new ArrayList<Integer>();
}

private void mapListToValues(ListNode head) {
while (head != null) {
this.values.add(head.val);
head = head.next;
}
}

private TreeNode convertListToBST(int left, int right) {
// Invalid case
if (left > right) {
return null;
}

// Middle element forms the root.
int mid = (left + right) / 2;
TreeNode node = new TreeNode(this.values.get(mid));

// Base case for when there is only one element left in the array
if (left == right) {
return node;
}

// Recursively form BST on the two halves
node.left = convertListToBST(left, mid - 1);
node.right = convertListToBST(mid + 1, right);
return node;
}

public TreeNode sortedListToBST(ListNode head) {

// Form an array out of the given linked list and then
// use the array to form the BST.
this.mapListToValues(head);

// Convert the array to
return convertListToBST(0, this.values.size() - 1);
}
}

快慢指针

来源题解

  1. 由于我们得到的是一个有序链表而不是数组,我们不能直接使用下标来访问元素。我们需要知道链表中的中间元素。
  2. 我们可以利用两个指针来访问链表中的中间元素。假设我们有两个指针 slow_ptrfast_ptrslow_ptr 每次向后移动一个节点而 fast_ptr 每次移动两个节点。当 fast_ptr 到链表的末尾时 slow_ptr 就访问到链表的中间元素。对于一个偶数长度的数组,中间两个元素都可用来作二叉搜索树的根。
  3. 当找到链表中的中间元素后,我们将链表从中间元素的左侧断开,做法是使用一个 prev_ptr 的指针记录 slow_ptr 之前的元素,也就是满足 prev_ptr.next = slow_ptr。断开左侧部分就是让 prev_ptr.next = None
  4. 我们只需要将链表的头指针传递给转换函数,进行高度平衡二叉搜索树的转换。所以递归调用的时候,左半部分我们传递原始的头指针;右半部分传递 slow_ptr.next 作为头指针。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* Definition for singly-linked list. public class ListNode { int val; ListNode next; ListNode(int
* x) { val = x; } }
*/
/**
* Definition for a binary tree node. public class TreeNode { int val; TreeNode left; TreeNode
* right; TreeNode(int x) { val = x; } }
*/
class Solution {

private ListNode findMiddleElement(ListNode head) {

// The pointer used to disconnect the left half from the mid node.
ListNode prevPtr = null;
ListNode slowPtr = head;
ListNode fastPtr = head;

// Iterate until fastPr doesn't reach the end of the linked list.
while (fastPtr != null && fastPtr.next != null) {
prevPtr = slowPtr;
slowPtr = slowPtr.next;
fastPtr = fastPtr.next.next;
}

// Handling the case when slowPtr was equal to head.
if (prevPtr != null) {
prevPtr.next = null;
}

return slowPtr;
}

public TreeNode sortedListToBST(ListNode head) {

// If the head doesn't exist, then the linked list is empty
if (head == null) {
return null;
}

// Find the middle element for the list.
ListNode mid = this.findMiddleElement(head);

// The mid becomes the root of the BST.
TreeNode node = new TreeNode(mid.val);

// Base case when there is just one element in the linked list
if (head == mid) {
return node;
}

// Recursively form balanced BSTs using the left and right halves of the original list.
node.left = this.sortedListToBST(head);
node.right = this.sortedListToBST(mid.next);
return node;
}
}

二分

来自范例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Solution {

private ListNode head;

private int findSize(ListNode head) {
ListNode ptr = head;
int c = 0;
while (ptr != null) {
ptr = ptr.next;
c += 1;
}
return c;
}

private TreeNode convertListToBST(int l, int r) {
// Invalid case
if (l > r) {
return null;
}

int mid = (l + r) / 2;

// First step of simulated inorder traversal. Recursively form
// the left half
TreeNode left = this.convertListToBST(l, mid - 1);

// Once left half is traversed, process the current node
TreeNode node = new TreeNode(this.head.val);
node.left = left;

// Maintain the invariance mentioned in the algorithm
this.head = this.head.next;

// Recurse on the right hand side and form BST out of them
node.right = this.convertListToBST(mid + 1, r);
return node;
}

public TreeNode sortedListToBST(ListNode head) {
// Get the size of the linked list first
int size = this.findSize(head);

this.head = head;

// Form the BST now that we know the size
return convertListToBST(0, size - 1);
}
}