[LeetCode] 109. Convert Sorted List to Binary Search Tree

本文介绍如何将一个按升序排列的单向链表转换为高度平衡的二叉搜索树。通过使用双指针法寻找链表中点,并以此作为二叉树的根节点,递归构建左右子树,确保每个节点的左右子树高度差不超过1。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接: 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;
    }
}

参考资料

https://www.cnblogs.com/grandyang/p/4295618.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值