[LeetCode]109. 有序链表转换二叉搜索树(java实现)
1. 题目
2. 读题(需要重点注意的东西)
- 需要注意的是,要建立的是一颗二叉搜索树,而二叉搜索树的建立,类似于二分查找法;
- 难点在于如何对链表进行二分查找(链表不具有数组那样能直接访问的特性)(快慢指针,具体请看下方代码)
- 树的建立过程还是如下代码所示,关键就在于如何得到中间的节点mid
// 建立根节点
TreeNode root = new TreeNode(slow.val);
// 递归建立左子树
root.left = helper(start,mid);
// 递归建立右子树
root.right = helper(mid+1,end);
3. 解法
解法:递归
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
// 链表构建一棵树与数组的不同之处在于链表不能直接访问其中的对象
// 链表求中点的方法:快慢指针(快指针每次走两步,慢指针每次走一步,当快指针走到null时,慢指针指向的值就是中点)
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if(head == null) return null;
return helper(head,null);
}
private TreeNode helper(ListNode start, ListNode end){
if(start == end) return null;
ListNode slow = start;
ListNode fast = start;
// 当快指针走到终点时,慢指针指向的节点,即为链表的中间节点
while(fast != end && fast.next != end){
// 慢指针一次走一步
slow = slow.next;
// 快指针一次走两步
fast = fast.next.next;
}
TreeNode root = new TreeNode(slow.val);
// 左半部分递归
root.left = helper(start, slow);
// 右半部分递归
root.right = helper(slow.next, end);
return root;
}
}
4. 可能有帮助的前置习题
[LeetCode]108. 将有序数组转换为二叉搜索树(java实现)
5. 所用到的数据结构与算法思想
- 二叉搜索树(BST)的性质(主要是类似二分查找的左小右大性质)
- 如何得到链表的中间节点—快慢指针
- 递归法
6. 总结
-
二叉搜索树相关问题,最主要的思路是利用二叉搜索树的性质:即左子树的节点都比根节点小,右子树的节点值都比根节点大(因此经过中序遍历就是一个从小到大排列的数组,中序遍历翻转就能得到从大到小排列的数组),这种性质与二分查找的思想也是一致的,因此一颗BST的建立,靠的就是二分查找的思想。
-
同时,要知道如何用代码实现一棵树的建立,即建立根节点
new TreeNode(val)
再递归建立左右子树
root.left = creatTree(root.left);
root.right= creatTree(root.right); -
最后,需要知道得到链表中间节点的方法—快慢指针