原题链接: https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/
1. 题目介绍
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.
给出一个按照递增排序的单向链表,将其转换成一个高度平衡的二叉树。
高度平衡的二叉树的意思是,每个节点左右两个子树的高度向差不会大于1. 注意是每个节点,不仅仅是根节点。
2. 解题思路
这个题我一开始对高度平衡的二叉树理解有误,以为是根节点两边的子树高度相差不超过1就可以了,但是后来发现是每个节点都要满足这个条件。我下面的解法参考了 https://www.cnblogs.com/grandyang/p/4295618.html 的介绍,有兴趣的读者可以直接去看原文。
假设二叉树的根节点是 root ,root 的左子树里面都是比 root 小的数,root 的右子树里面都是比它大的数。所以想到 root 是所有节点的中位数。
数组是已经排好序的,为了找到中位数,可以先找到排在最中间的节点。这里就用到了双指针法来寻找链表最中间的节点。
设置一个快指针 fast ,一个慢指针 slow ,两个指针一开始都指向 head 。fast 每次走两步,slow 每次走1步。当 fast 走到链表的尾部时,slow 就会走到链表的中间,slow 所指的节点就可以把链表从中间一分为二了。
利用上述方法,可以先找到链表的中点,然后以中点的值建立一个数的根节点。
之后需要把原链表断开,分为前后两个链表,都不能包含原来的中点,然后再分别对这两个链表递归调用原函数,分别连上左右子节点即可。
实现代码
/**
* 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 {
public TreeNode sortedListToBST(ListNode head) {
if(head == null ){
return null;
}
return recursion(head,null);
}
public TreeNode recursion(ListNode head,ListNode tail){
//如果链表已经结束,则返回null
if(head == tail){
return null;
}
//寻找链表的中间节点,从中间将其一分为二
ListNode fast = head;
ListNode slow = head;
while(fast != tail && fast.next != tail){
fast = fast.next.next;
slow = slow.next;
}
//链表从slow所指的节点分开为两段
//第一段从head开始,到slow的前一个结束
//第二段从slow.next开始,到tail结束
TreeNode cur = new TreeNode(slow.val);
cur.left = recursion(head,slow);
cur.right = recursion(slow.next,tail);
return cur;
}
}