欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[leetcode每日一题2020/8/18]109. 有序链表转换二叉搜索树

程序员文章站 2022-07-12 23:07:34
...

题目来源于leetcode,解法和思路仅代表个人观点。传送门
难度:中等
用时:忘了,应该不是很久,一开始还没想到【中序遍历】

题目

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

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

示例:

给定的有序链表: [-10, -3, 0, 5, 9],

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

      0
     / \
   -3   9
   /   /
 -10  5

思路

一开始确实是想到【中序遍历】的思路生成树。但是想着想着,就变成【先序遍历】了。

每个的左边部分(比这个数小)都在他的左子树中,每个的右边部分(比这个数大)都在他的右子树中。


先序遍历的思路
那每次可以去这个数组的中间部分作为根节点,再对左半部分右半部分进行递归操作。
注意:由于给出的是【链表】,则需要把【链表】转换成数组,再操作。那么,时间复杂度至少都是O(n)了。


中序遍历的思路
对于【链表】,要是可以对树进行,从小到大进行插入,就可以实现了。
由于要求是平衡搜索树,那么,对于位置处于中间的结点比它小的数,和比它大的数(如果不考虑相等的情况),应该最多相差1个
那么,我们每次取,中间结点的,左半部分右半部分进行递归操作即可。
注意:由于要取【中间】结点,那么我们必须要知道链表的长度。那么,时间复杂度也至少O(n)。

代码

/**
 * 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;
 *     }
 * }
 */

分治+先序遍历

class Solution {
    List<Integer> list = new ArrayList<>();
    public TreeNode sortedListToBST(ListNode head) {
        link2Array(head);
        TreeNode root = new TreeNode();
        TreeNode tree = insertNode(0,list.size()-1);
        return tree;
    }
    public TreeNode insertNode(int beg,int end){
        if(beg>end){
            return null;
        }
        int mid = (beg + end) / 2;
        TreeNode root = new TreeNode();
        root.val = list.get(mid);
        root.left = insertNode(beg,mid-1);
        root.right = insertNode(mid+1,end);

        return root;
    }
    public void link2Array(ListNode node){
        while(node!=null){
            list.add(node.val);
            node = node.next;
        }
    }
}

分治+中序遍历

(官方给出)

class Solution {
    ListNode globalHead;
    public TreeNode sortedListToBST(ListNode head) {
        globalHead = head;
        int length = getLength(head);
        return buildTree(0, length - 1);
    }

    public int getLength(ListNode head) {
        int ret = 0;
        while (head != null) {
            ++ret;
            head = head.next;
        }
        return ret;
    }

    public TreeNode buildTree(int left, int right) {
        if (left > right) {
            return null;
        }
        int mid = (left + right + 1) / 2;
        TreeNode root = new TreeNode();
        root.left = buildTree(left, mid - 1);
        root.val = globalHead.val;
        globalHead = globalHead.next;
        root.right = buildTree(mid + 1, right);
        return root;
    }
}

算法复杂度

时间复杂度: O(n)。其中n为链表的长度。每个结点遍历2遍。
空间复杂度: 先序遍历:O(n),n为结点数。中序遍历:O(logn),n为栈的最大深度。
先序遍历:
[leetcode每日一题2020/8/18]109. 有序链表转换二叉搜索树
中序遍历:
[leetcode每日一题2020/8/18]109. 有序链表转换二叉搜索树

相关标签: 算法 leetcode