[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为栈的最大深度。
先序遍历:
中序遍历: