Open azl397985856 opened 2 years ago
use the middle point of the linkedlist as the root, the left part to the middle point is the left subtree and the right part to the middle point is the right subtree. Use two pointers to find out the middle point.
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if (head == null) {
return null;
}
ListNode slow = head, fast = head, prev = null;
while (fast != null && fast.next != null) {
prev = slow;
slow = slow.next;
fast = fast.next.next;
}
TreeNode root = new TreeNode(slow.val);
if (slow != head) {
prev.next = null;
root.left = sortedListToBST(head);
}
root.right = sortedListToBST(slow.next);
return root;
}
}
Time: O(n) Space: O(n)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
"""
Ideas:
get length of LL
connect tail to node
prev, cur = head, head
-> go next (l - k) times to get new head at cur
TC: O(n)
SC: O(1)
"""
if not head: return
l = 1
tail = head
while tail.next:
tail = tail.next
l += 1
tail.next = head
prev, cur = tail, head
count = l - k % l
# print(count)
while count > 0:
# print(prev.val, cur.val)
cur = cur.next
prev = prev.next
count -= 1
prev.next = None
return cur
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
"""
topic: LinkedList, rotate
ideas:
slow,fast two pointers
get slow point to new head, fast point to end
reconnect to get new LinkedList
TC: O(n)
SC: O(1)
"""
if not head or not head.next: return head
count = 0
cur = head
while cur:
cur = cur.next
count += 1
k = k % count
slow, fast = head, head
while fast.next:
if k <= 0:
slow = slow.next
fast = fast.next
k -= 1
fast.next = head
res = slow.next
slow.next = None
return res
找到每次中间的节点,然后断开链接,两边选中点,递归。
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
def process(head):
if not head:
return head
if not head.next:
return TreeNode(head.val)
fast = slow = head
pre = None
while fast and fast.next:
fast = fast.next.next
pre = slow
slow = slow.next
pre.next = None
tree = TreeNode(slow.val)
tree.right = process(slow.next)
tree.left = process(head)
return tree
return process(head)
空间复杂度 Ologn 时间复杂度 Onlogn
快慢指针递归
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
if (nullptr == head) return nullptr;
return getTree(head, nullptr);
}
TreeNode* getTree(ListNode* startPtr, ListNode* endPtr){
if (startPtr == endPtr) return nullptr;
ListNode* lowPtr = startPtr;
ListNode* fastPtr = startPtr;
while(endPtr != fastPtr && endPtr != fastPtr->next){
lowPtr = lowPtr->next;
fastPtr = fastPtr->next->next;
}
TreeNode* root = new TreeNode(lowPtr->val);
root->left = getTree(startPtr,lowPtr);
root->right = getTree(lowPtr->next,endPtr);
return root;
}
};
class Solution { public TreeNode sortedListToBST(ListNode head) { return build(head, null); } //[start, end) TreeNode build(ListNode start, ListNode end){ if(start == end){ return null; }
ListNode mid = findMid(start, end);
TreeNode root = new TreeNode(mid.val);
root.left = build(start, mid);
root.right = build(mid.next, end);
return root;
}
//two pointers
ListNode findMid(ListNode start, ListNode end){
ListNode slow = start, fast = start;
while (fast != end && fast.next != end){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
用快慢指针查找链表的中间节点,中间节点就是父节点。
从中间节点分成左右两个链表,再分别查找左右两个链表的中间节点作为左右子节点,以此类推
var sortedListToBST = function(head) {
if (head === null) return head;
if (head.next === null) return new TreeNode(head.val);
return getRoot(head, null);
};
let getRoot = function(start, end) {
if (start === end) return null;
let fast = start, slow = start;
while (fast !== end && fast.next !== end) {
slow = slow.next;
fast = fast.next.next;
}
return new TreeNode(slow.val, getRoot(start, slow), getRoot(slow.next, end));
}
function sortedListToBST(head: ListNode | null): TreeNode | null {
let tree_root: TreeNode = new TreeNode();
let data_arr = [];
if (head === null) {
return null;
}
while (head !== null) {
data_arr.push(head.val);
head = head.next;
}
convertBST(data_arr, tree_root, 0, data_arr.length);
return tree_root;
};
function convertBST(arr_tree: number[], root: TreeNode, start_position: number, convert_length: number) {
let left_length: number;
let right_length: number;
let tree_left: TreeNode = new TreeNode();
let tree_right: TreeNode = new TreeNode();
root.left = null;
root.right = null;
root.val = arr_tree[start_position + Math.floor(convert_length / 2)];
left_length = Math.floor(convert_length / 2);
right_length = convert_length - left_length - 1;
if (left_length > 0) {
root.left = tree_left;
convertBST(arr_tree, root.left, start_position, left_length);
}
if (right_length > 0) {
root.right = tree_right;
convertBST(arr_tree, root.right, start_position + left_length + 1, right_length);
}
}
var sortedListToBST = function(head) {
return toBST(toArray(head))
};
const toArray = head => {
const arr = []
while (head) {
arr.push(head.val)
head = head.next
}
return arr
}
const toBST = (arr, l = 0, r = arr.length) => {
if (l === r) return null
const m = Math.floor((l + r) / 2)
const root = new TreeNode(arr[m])
root.left = toBST(arr, l, m)
root.right = toBST(arr, m + 1, r)
return root
}
主要是利用二叉搜索树的性质,二叉搜索树的中序遍历是一个有序数列。 构建二叉树的前提是中序遍历+任何其他遍历,中序遍历确定左右子树,其他遍历确认根节点。这里已经知道中序遍历,所以只需要找根节点。因为要构建平衡二叉搜索树,所以需要两边一样多,所以根节点就是有序数列的中位数。
class Solution {
public:
int getListSize(ListNode *head)
{
int ret=0;
while(head){
ret++;
head=head->next;
}
return ret;
}
TreeNode* sortedListToBST(ListNode* head) {
if(!head) return nullptr;
if(!(head->next)){
TreeNode *ret=new TreeNode(head->val);
return ret;
}
int size=getListSize(head);
int mid= size>>1;
int i=0;
ListNode* pre_list=head;
while(i<mid-1){
pre_list=pre_list->next;
i++;
}
ListNode *cur=pre_list->next;
ListNode *post=cur->next;
pre_list->next=nullptr;
TreeNode *root=new TreeNode(cur->val);
root->left=sortedListToBST(head);
root->right=sortedListToBST(post);
return root;
}
};
class Solution {
public TreeNode sortedListToBST(ListNode head) {
List<Integer> valRecord = new ArrayList<>();
ListNode currentNode = head;
while (currentNode!=null) {
valRecord.add(currentNode.val);
currentNode = currentNode.next;
}
int[] nums = new int[valRecord.size()];
for(int i = 0; i < valRecord.size(); i++) {
nums[i] = valRecord.get(i);
}
return sortedListToBSTHelper(nums, 0, nums.length-1);
}
public TreeNode sortedListToBSTHelper(int[] nums, int left, int right) {
if(left == right)
return new TreeNode(nums[left]);
if(left > right)
return null;
int mid = left + (right-left)/2;
int val = nums[mid];
TreeNode leftNode = sortedListToBSTHelper(nums,left, mid-1);
TreeNode rightNode = sortedListToBSTHelper(nums, mid+1, right);
return new TreeNode(val, leftNode, rightNode);
}
}
class Solution {
static TreeNode build(int[] nums, int l, int r)
{
if(l > r) return null;
int k = (l + r) / 2;
TreeNode root = new TreeNode(nums[k]);
root.left = build(nums, l, k - 1);
root.right = build(nums, k + 1, r);
return root;
}
public TreeNode sortedArrayToBST(int[] nums) {
int n = nums.length;
return build(nums,0,n - 1);
}
public TreeNode sortedListToBST(ListNode head) {
int k = 0;
ListNode p = head;
while(p != null)
{
k ++;
p = p.next;
}
int[] nums = new int[k];
p = head;
int t = 0;
while(p != null)
{
nums[t ++] = p.val;
p = p.next;
}
return sortedArrayToBST(nums);
}
}
Day9
1、二叉搜索树要求左子树必须小于父节点,右子树必须大于父节点
2、获取中间节点的位置,并且分别向左右两侧找左子树和右子树
3、 递归调用
var sortedListToBST = function (head) {
if (!head) return null;
return dfs(head, null);
};
function dfs(head, tail) {
if (head == tail) return null;
let fast = head;
let slow = head;
while (fast != tail && fast.next != tail) {
fast = fast.next.next;
slow = slow.next;
}//快慢指针分别获取链表的中间位置和末尾位置
let root = new TreeNode(slow.val);//中间位置设为根节点
root.left = dfs(head, slow);//选择中间位置左边的节点的中间位置作为左子节点
root.right = dfs(slow.next, tail);
return root;
}
时间复杂度:O(nlogn)
空间复杂度:O(logn)
class Solution { public: TreeNode sortedListToBST(ListNode head) { if (nullptr == head) return nullptr; return getTree(head, nullptr); } TreeNode getTree(ListNode startPtr, ListNode endPtr){ if (startPtr == endPtr) return nullptr; ListNode lowPtr = startPtr; ListNode fastPtr = startPtr; while(endPtr != fastPtr && endPtr != fastPtr->next){ lowPtr = lowPtr->next; fastPtr = fastPtr->next->next; } TreeNode root = new TreeNode(lowPtr->val); root->left = getTree(startPtr,lowPtr); root->right = getTree(lowPtr->next,endPtr); return root; } };
快慢指针
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
if not head:
return head
pre, slow, fast = None, head, head
while fast and fast.next:
fast = fast.next.next
pre = slow
slow = slow.next
if pre:
pre.next = None
node = TreeNode(slow.val)
if slow == fast:
return node
node.left = self.sortedListToBST(head)
node.right = self.sortedListToBST(slow.next)
return node
leetcode 109 https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/solution/109-you-xu-lian-biao-zhuan-huan-er-cha-s-lzlb/ 链表转成数组
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if (null==head) {
return null;
}
List<Integer> nums = new ArrayList<>();
while (null!=head) {
nums.add( head.val );
head = head.next;
}
return toBst(nums,0, nums.size()-1);
}
private TreeNode toBst( List<Integer> nums, int left, int right ) {
if (left>right) {
return null;
}
int middle = left + (right - left)/2;
TreeNode root = new TreeNode(nums.get( middle ));
root.left = toBst( nums,left,middle-1 );
root.right = toBst( nums,middle+1,right );
return root;
}
}
递归左右两部分
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def getRootNode(self,head,tail):
if head is None :
return None
if head.next is None:
return TreeNode(head.val)
if head == tail:
return TreeNode(head.val)
premid = head
mid = head.next
if mid == tail:
t =tail
else:
t = mid.next
while(t != tail and t.next!=tail):
t = t.next.next
premid = mid
mid = mid.next
if mid == tail:
aftermid = None
else:
aftermid = mid.next
return TreeNode(mid.val,self.getRootNode(head,premid),self.getRootNode(aftermid,tail))
def sortedListToBST(self, head):
"""
:type head: Optional[ListNode]
:rtype: Optional[TreeNode]
"""
if head is None:
return None
if head.next is None:
return TreeNode(head.val)
premid = head
mid = head.next
tail = mid.next
aftermid = tail
while(tail is not None and tail.next is not None):
tail = tail.next.next
premid = mid
mid = mid.next
aftermid = mid.next
return TreeNode(mid.val,self.getRootNode(head,premid),self.getRootNode(aftermid,tail))
时间复杂度为O(nlogn) 空间复杂度为O(n)
先把链表转化为数组,找到中间位置作为root,再对左右递归
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
arr = []
while head:
arr.append(head.val)
head = head.next
def buildBST(start, end):
if start > end: return None
mid = (start + end) // 2
root = TreeNode(arr[mid])
root.left = buildBST(start, mid - 1)
root.right = buildBST(mid + 1, end)
return root
return buildBST(0, len(arr)-1)
利用递归的方法。
快慢指针找到中点,
1 2 3 4 5 中点 3
1 2 3 4 5 6 中点 3
中点的左指针指向 他的左边。 右指针指向右边。
递归返回值: 返回中间节点。
递归参数: 头结点,尾结点。
结束条件: 当前链表全为nullptr的时候
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
return getTree(head, nullptr);
}
TreeNode* getTree(ListNode* head, ListNode* tail) {
// 结束条件
if (head == tail) {
return nullptr;
}
// 快慢指针找到中间节点。中间节点= p_slow
ListNode *p_slow = head, *p_quick = head;
while(p_quick != tail && p_quick->next != tail) {
p_slow = p_slow->next;
p_quick = p_quick->next->next;
}
// 创建中间节点
TreeNode *t_mid = new TreeNode(p_slow->val);
t_mid->left = getTree(head, p_slow);
t_mid->right = getTree(p_slow->next, tail);
return t_mid;
}
};
时间:NLog(N) 每个节点都要遍历,并且都还会有一个二分遍历
空间:LogN 每个二分遍历需要建一个快慢指针
先获取根节点,再利用分治方法构造左右子树。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
def getMid(left,right):
fast = slow = left
while fast!=right and fast.next!=right:
fast = fast.next.next
slow = slow.next
return slow
def buildTree(left,right):
if left == right:
return None
# 寻找根节点
mid = getMid(left,right)
# 构造根节点
root = TreeNode(mid.val)
# 构造左子树
root.left = buildTree(left,mid)
# 构造右子树
root.right = buildTree(mid.next,right)
return root
return buildTree(head,None)
https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/
给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差不超过 1。
示例 1:
输入: head = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5]
解释: 一个可能的答案是[0,-3,9,-10,null,5],它表示所示的高度平衡的二叉搜索树。
示例 2:
输入: head = []
输出: []
提示:
head 中的节点数在[0, 2 * 104] 范围内
-105 <= Node.val <= 105
通过判断当前节点处于左指针还是右指针
JavaScript Code:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {ListNode} head
* @return {TreeNode}
*/
const sortedListToBST = (head) => {
const arr = [];
while (head) { // 将链表节点的值逐个推入数组arr
arr.push(head.val);
head = head.next;
}
// 根据索引start到end的子数组构建子树
const buildBST = (start, end) => {
if (start > end) return null; // 指针交错,形成不了子序列,返回null节点
const mid = Math.floor((start+end)/2); // 求中间索引 中间元素是根节点的值
const root = new TreeNode(arr[mid]); // 创建根节点
root.left = buildBST(start, mid - 1); // 递归构建左子树
root.right = buildBST(mid + 1, end); // 递归构建右子树
return root; // 返回当前子树
};
return buildBST(0, arr.length - 1); // 根据整个arr数组构建
};
复杂度分析
令 n 为数组长度。
def sortedListToBST(self, head):
def findmid(head,tail):
slow,fast=head,head
while fast!=tail and fast.next!=tail:
fast=fast.next.next
slow=slow.next
return slow
def helper(head,tail):
if head==tail:return
node=findmid(head,tail)
root=TreeNode(node.val)
root.left=helper(head,node)
root.right=helper(node.next,tail)
return root
return helper(head,None)
没得思路,看的官方题解😢。
class Solution {
public TreeNode sortedListToBST(ListNode head) {
return buildTree(head, null);
}
public TreeNode buildTree(ListNode left, ListNode right) {
if (left == right) {
return null;
}
ListNode mid = getMedian(left, right);
TreeNode root = new TreeNode(mid.val);
root.left = buildTree(left, mid);
root.right = buildTree(mid.next, right);
return root;
}
public ListNode getMedian(ListNode left, ListNode right) {
ListNode fast = left;
ListNode slow = left;
while (fast != right && fast.next != right) {
fast = fast.next;
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
复杂度分析
思路:参考官方思路,递归的形成平衡二叉树,对于一段链表来说,递归的过程就是找到中间节点,作为根节点,同时调用函数,把左右两个链表分别转化成左子树和右子树,返回左子树和右子树的根节点,作为该根节点的左右子节点即可。 注意是要把中间节点左右链表变成两个子链表需要让中间节点前一个节点断开,指向None.
代码如下:
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
if not head:
return None
fast = head
slow = head
pre = None
while fast and fast.next:
fast = fast.next.next
pre = slow
slow = slow.next
root = TreeNode(val=slow.val)
if not pre:
return root
pre.next = None
root.left = self.sortedListToBST(head)
root.right = self.sortedListToBST(slow.next)
return root
复杂度分析: 时间复杂度:递归深度为O(log N),每次递归需要遍历整个递归链表,即O(Nlog N) 空间复杂度:递归深度为O(log N),因为每次递归,问题规模变为原来的一半,规模指数下降,所以空间复杂度为O(log N)
1、二分查找使用快慢指针找到中间节点
2、使用递归
var sortedListToBST1 = function(head) {
if(head === null) return null;
if(head.next === null) return new TreeNode(head.val);
let fast = head.next.next;
let slow = head;
while(fast !== null && fast.next !== null){
slow = slow.next;
fast = fast.next.next;
}
let root = new TreeNode(slow.next.val);
let rightHead = slow.next.next;
slow.next = null;
root.left = sortedListToBST1(head);
root.right = sortedListToBST1(rightHead);
return root;
};
时间复杂度:O(nlogn)
空间复杂度:O(logn)
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if (head == null) {
return null;
}
List<Integer> list = new ArrayList<>();
while (head != null) {
list.add(head.val);
head = head.next;
}
return helper(list, 0, list.size() - 1);
}
private TreeNode helper(List<Integer> list, int start, int end) {
if (start > end) {
return null;
}
int mid = (start + end) / 2;
TreeNode root = new TreeNode(list.get(mid));
root.left = helper(list, start, mid - 1);
root.right = helper(list, mid + 1, end);
return root;
}
}
一个函数找中点,一个函数递归构造左右子树。
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
def findMid(left,right):
fast,slow = left,left
while fast!=right and fast.next!=right:
fast=fast.next.next
slow=slow.next
return slow
def bulidTree(left,right):
if left==right:
return None
mid = findMid(left,right)
root = TreeNode(mid.val)
root.left=bulidTree(left,mid)
root.right=bulidTree(mid.next,right)
return root
# root = bulidTree(head,None)
return bulidTree(head,None)
class Solution {
public TreeNode sortedListToBST(ListNode head) {
return convert(head,null);
}
//转换方法
public TreeNode convert(ListNode left,ListNode right){
if(left == right){
return null;
}
//得到中间值,然后递归处理两边
ListNode mid = getMedian(left,right);
TreeNode root = new TreeNode(mid.val);
//right为null和mid,left为left和mid.next
root.left = convert(left,mid);
root.right = convert(mid.next,right);
return root;
}
//中间值
public ListNode getMedian(ListNode left,ListNode right){
ListNode slow = left;
ListNode fast = left;
while(fast != right && fast.next != right){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
快慢指针,分割,递归
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if(head == null) return null;
if(head.next == null) return new TreeNode(head.val);
ListNode fast = head, slow = head, pre = null;
while(fast != null && fast.next != null){
fast = fast.next.next;
pre = slow;
slow = slow.next;
}
pre.next = null;
ListNode rightList = slow.next;
TreeNode root = new TreeNode(slow.val);
root.left = sortedListToBST(head);
root.right = sortedListToBST(rightList);
return root;
}
}
时间:O(nlogn)
空间:O(logn)
use dummy head, find mid, break into halves, disconnect, recursively build the tree
Time:
T(1) = T(0) = 1
T(n) = 2 * T(n/2) + O(n/2) -> extra linear traversal
= 2 * [2 * T(n/4) + O(n/4)] + O(n/2)
= 4 * T(n/4) + O(n)
= 4 * [2 * T(n/8) + O(n/8)] + O(n)
= 8 * T(n/8) + 3 * O(n/2)
= x * T(n/x) + log x * O(n/2)
n/x = 1, n = x
T(n) = n * T(1) + logn * O(n) = n + nlogn = nlogn
Space:
tree: O(n), n = len of linkedlist
stack: O(height) = O(logn)
/**
* 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 {
public TreeNode sortedListToBST(ListNode head) {
if (head == null) return null;
// must deal with the one node case as the base case
if (head.next == null) return new TreeNode(head.val, null, null);
ListNode dummy = new ListNode(0, head);
ListNode fast = head, slow = dummy;
while (fast != null && fast.next != null) { // 1-2-3-4
fast = fast.next.next;
slow = slow.next;
}
ListNode rootList = slow.next;
ListNode nextHead = rootList.next;
slow.next = null;
rootList.next = null;
TreeNode root = new TreeNode(rootList.val);
root.left = sortedListToBST(head);
root.right = sortedListToBST(nextHead);
return root;
}
}
参考第108,先把链表的值拷贝到数组中,再对数组进行递归。
var sortedListToBST = function(head) {
let arr=[];
let temp=head;
while (temp){
arr.push(temp.val);
temp=temp.next;
}
return dfs(0,arr.length-1,arr);
};
function dfs(l,r,arr){
//let mid=Math.floor(l+(r-l)/2);
let mid=parseInt(r+(l-r)/2);
if (l>r) return null;
let root=new TreeNode(arr[mid]);
root.left=dfs(l,mid-1,arr);
root.right=dfs(mid+1,r,arr);
return root;
}
空间复杂度O{n} 时间复杂度O(nlogn)
分治
时间复杂度:O(n log n) 空间复杂度:O(log n)
public TreeNode sortedListToBST(ListNode head) {
return buildTree(head, null);
}
public TreeNode buildTree(ListNode left, ListNode right) {
if (left == right) {
return null;
}
ListNode mid = getMedian(left, right);
TreeNode root = new TreeNode(mid.val);
root.left = buildTree(left, mid);
root.right = buildTree(mid.next, right);
return root;
}
public ListNode getMedian(ListNode left, ListNode right) {
ListNode fast = left;
ListNode slow = left;
while (fast != right && fast.next != right) {
fast = fast.next;
fast = fast.next;
slow = slow.next;
}
return slow;
}
用快慢指针和递归
# Definition for singly-linked list.
# class ListNode:
#
def
init (self, val=0, next=None) :
#
self. val = val
#self.next = next
# Definition for a binary tree node .
# class TreeNode :
#def init_ (self, val=0, left=None, right=None)
#self.val = val
#self.left = left
#self. right = right
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
if not head:
return head
fast, slow, pre = head, head, None
while fast and fast.next:
fast = fast.next.next
pre = slow
slow = slow.next
if pre:
pre.next = None
node = TreeNode(slow,val)
if slow == fast:
return node
node. left = self.sortedListToBST (head)
node.right = self.sortedListToBST(slow.next)
return node
时间:O(n) 空间:O(n)
代码
class Solution {
public:
TreeNode sortedListToBST(ListNode head) {
TreeNode* root;
if(!head)
return nullptr;
if(!head->next){
root = new TreeNode(head->val);
return root;
}
ListNode *slow = head;
ListNode *fast = head;
ListNode *prev = head;
while(fast != NULL && fast->next != NULL){
fast = fast->next->next;
slow = slow->next;
}
while(prev->next != slow)
prev = prev->next;
root = new TreeNode(slow->val);
ListNode* headRight = slow->next;
prev->next = nullptr;
root->left = sortedListToBST(head);
root->right = sortedListToBST(headRight);
return root;
}
};
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
找到链表的中心节点,然后用同样的方法递归建立左子树和右子树。时间复杂度 O(nlogn)。找到中心节点 花费了O(n)时间,一共递归logn
class Solution(object):
def sortedListToBST(self, head):
"""
:type head: Optional[ListNode]
:rtype: Optional[TreeNode]
"""
if not head:
return head;
return self.helper(head, None)
def helper(self, head,tail):
if head == tail:
return None;
slow, fast = head, head;
while fast != tail and fast.next != tail:
fast = fast.next.next;
slow = slow.next;
node = TreeNode(slow.val);
node.left = self.helper(head, slow);
node.right = self.helper(slow.next, tail);
return node;
优化时间复杂度, 把链表转换为数组,这样查询mid的时间复杂度为O(1), 总共有n个节点,时间复杂度为O(n)。 空间复杂度O(n)
class Solution(object):
def sortedListToBST(self, head):
"""
:type head: Optional[ListNode]
:rtype: Optional[TreeNode]
"""
arr = self.transform_into_array(head);
return self.helper(arr, 0, len(arr)-1);
def transform_into_array(self, head):
res = [];
while head:
res.append(head.val);
head = head.next;
return res;
def helper(self,arr,left, right):
if left > right:
return None;
mid = (left + right) // 2;
node = TreeNode(arr[mid]);
if left == right:
return node;
node.left = self.helper(arr,left, mid-1);
node.right = self.helper(arr,mid+1,right);
return node;
https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/
给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差不超过 1。
示例 1:
输入: head = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5]
解释: 一个可能的答案是[0,-3,9,-10,null,5],它表示所示的高度平衡的二叉搜索树。
示例 2:
输入: head = []
输出: []
提示:
head 中的节点数在[0, 2 * 104] 范围内
-105 <= Node.val <= 105
Java Code:
/**
* 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 {
public TreeNode sortedListToBST(ListNode head) {
if(head==null){
return null;
}
return getMid(head,null);
}
//获取二叉树
TreeNode getMid(ListNode head,ListNode tail){
//边界
if(head==tail){
return null;
}
//中间节点,快慢指针
ListNode fast=head;
ListNode slow =head;
//快指针到尾部,或者为他后面为链表结束
while(fast != tail && fast.next != tail){
fast = fast.next.next;
slow = slow.next;
}
//慢指针就是中点
TreeNode root = new TreeNode(slow.val);
root.left = getMid(head, slow);
root.right = getMid(slow.next, tail);
return root;
}
}
复杂度分析
令 n 为链表长度。(算不来。。)
递归
TreeNode* sortedListToBST(ListNode* head) {
TreeNode *root;
if(!head) return nullptr;
if(!head->next){
root = new TreeNode(head->val);
return root;
}
ListNode* fast=head;
ListNode* slow=head;
ListNode* pre=head;
while(fast!=nullptr&&fast->next!=nullptr){
fast=fast->next->next;
slow=slow->next;
}
while(pre->next!=slow) pre=pre->next;
root=new TreeNode(slow->val);
ListNode* headright=slow->next;
pre->next=nullptr;
root->left=sortedListToBST(head);
root->right=sortedListToBST(headright);
return root;
}
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
def length(node):
cnt = 0
while node:
cnt += 1
node = node.next
return cnt
def inorder(l, r):
if l > r:
return None
mid = (l + r) // 2
left = inorder(l, mid - 1)
root = TreeNode(self.head.val)
self.head = self.head.next
root.left = left
root.right = inorder(mid + 1, r)
return root
self.head = head
n = length(head)
return inorder(0, n - 1)
Two pointer (fast & slow) to find middle node -> root Use recursion to build tree;
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if (head == null) {
return null;
}
return helper(head, null);
}
public TreeNode helper(ListNode head, ListNode tail) {
if (head == tail) {
return null;
}
ListNode fast = head;
ListNode slow = head;
while (fast != tail && fast.next != tail) { // !!
fast = fast.next.next;
slow = slow.next;
}
TreeNode root = new TreeNode(slow.val);
root.left = helper(head, slow);
root.right = helper(slow.next, tail);
return root;
}
}
Time: O(nlogn) n for traverse, logn for binary search Space: O(n)
注意当只有一个节点的时候要返回这个节点。获得中间节点的值,然后分别构建左右子树。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
if not head:
return None
if not head.next:
return TreeNode(head.val)
mid = self.findMid(head)
cur = mid.next
mid.next = None
root = TreeNode(cur.val)
root.left = self.sortedListToBST(head)
root.right = self.sortedListToBST(cur.next)
return root
def findMid(self, head):
if not head:
return None
p1, p2 = head,head
pre = None
while p2 and p2.next:
pre = p1
p1 = p1.next
p2 = p2.next.next
return pre
time O(N)
space O(1)
recursion.
每一次中中点作为root,然后再调用本函数 找left linked list, right linked list 的中点 作为sub tree 的root 节点。
其实有大量重复操作。
可以更简便把 linkedlist convert to list then build tree. 时间复杂度会降到O(N).
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
# break linked list
if not head: return None
if head and not head.next: return TreeNode(head.val)
fast, slow, prev = head, head, None
while fast and fast.next:
prev = slow
slow = slow.next
fast = fast.next.next
# slow is the root
prev.next = None
root = TreeNode(slow.val)
root.left = self.sortedListToBST(head)
root.right = self.sortedListToBST(slow.next)
return root
time complexity: O(N logN),每一次recurion 切一半.
space complexity: O(log N) call stack.
class Solution:
def helper(self, nodes, l, r):
if l > r:
return None
else:
mid = (l + r)//2
root = TreeNode(nodes[mid])
root.left = self.helper(nodes, l, mid-1)
root.right = self.helper(nodes, mid+1, r)
return root
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
nodes = []
p = head
while p:
nodes.append(p.val)
p = p.next
root = self.helper(nodes, 0, len(nodes)-1)
return root
time O(N)
space O(logN)
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
if head == None:
return head
pre, slow, fast = None, head, head
while fast and fast.next:
pre = slow
slow = slow.next
fast = fast.next.next
if pre:
pre.next = None
root = TreeNode(slow.val)
if slow == fast:
return root
root.left = self.sortedListToBST(head)
root.right =self.sortedListToBST(slow.next)
return root
空间复杂度:O(log N) 时间复杂度:O(N log N)
首先通过快两步慢一步针的方式找到中点
递归的方式,根节点等于中点,左节点等于左子树中点,右节点等于右子树中点
class Solution(object):
def sortedListToBST(self, head):
"""
:type head: Optional[ListNode]
:rtype: Optional[TreeNode]
"""
def getMid(left, right):
fast = slow = left # initial 先都从左侧第一个开始
while fast != right and fast.next != right:
fast = fast.next.next # 错误点,指针移动需用用自身,left.next一直是同一个,没有动
slow = slow.next
return slow
def buildTree(left, right):
if left == right:
return None
mid = getMid(left,right)
root = TreeNode(mid.val)
root.left = buildTree(left, mid)
root.right = buildTree(mid.next, right)
return root
return buildTree(head, None)
时间复杂度 O(nlogn)
空间复杂度 O(n)
109. 有序链表转换二叉搜索树
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/
前置知识
题目描述
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定的有序链表: [-10, -3, 0, 5, 9],
一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:
-3 9 / / -10 5