leetcode-pp / 91alg-7-daily-check

6 stars 0 forks source link

【Day 9 】2022-04-09 - 109. 有序链表转换二叉搜索树 #11

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

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], 它可以表示下面这个高度平衡二叉搜索树:

  0
 / \

-3 9 / / -10 5

shawnhu23 commented 2 years ago

Idea

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.

Code

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

Complexity

Time: O(n) Space: O(n)

yinhaoti commented 2 years ago
# 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
wychmod commented 2 years ago

思路

找到每次中间的节点,然后断开链接,两边选中点,递归。

代码

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

mo660 commented 2 years ago

思路

快慢指针递归

代码

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;
    }
};
floatingstarlight commented 2 years ago

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

}

miss1 commented 2 years ago

思路

用快慢指针查找链表的中间节点,中间节点就是父节点。

从中间节点分成左右两个链表,再分别查找左右两个链表的中间节点作为左右子节点,以此类推

代码

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));
}

复杂度分析

AConcert commented 2 years ago
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);
    }
}
ViviXu-qiqi commented 2 years ago
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
}
dtldtt commented 2 years ago

2022-04-09

109. 有序链表转换二叉搜索树

思路

主要是利用二叉搜索树的性质,二叉搜索树的中序遍历是一个有序数列。 构建二叉树的前提是中序遍历+任何其他遍历,中序遍历确定左右子树,其他遍历确认根节点。这里已经知道中序遍历,所以只需要找根节点。因为要构建平衡二叉搜索树,所以需要两边一样多,所以根节点就是有序数列的中位数。

代码


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

复杂度分析

备注

GaoMinghao commented 2 years ago
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);
    }
}
freedom0123 commented 2 years ago
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);
    }
}
KWDFW commented 2 years ago

Day9

109、有序链表转换二叉搜索树

javascript #树 #链表

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)

BruceLeeQAQ commented 2 years ago

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

bzlff commented 2 years ago

思路

快慢指针

代码

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
ShirAdaOne commented 2 years ago

思路

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;
    }
}
weihaoxie commented 2 years ago

思路

  1. 用快慢指针找到中间节点
  2. 递归左右两部分

    代码

    # 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)

linjunhe commented 2 years ago

思路

先把链表转化为数组,找到中间位置作为root,再对左右递归

Code (python3)

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)

复杂度分析

duantao74520 commented 2 years ago

思路:

利用递归的方法。

  1. 快慢指针找到中点,

    1 2 3 4 5 中点 3

    1 2 3 4 5 6 中点 3

  2. 中点的左指针指向 他的左边。 右指针指向右边。

  3. 递归返回值: 返回中间节点。

  4. 递归参数: 头结点,尾结点。

  5. 结束条件: 当前链表全为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 每个二分遍历需要建一个快慢指针

TonyLee017 commented 2 years ago

解题思路

先获取根节点,再利用分治方法构造左右子树。

代码

# 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)

复杂度分析

yaya-bb commented 2 years ago

题目地址(109. 有序链表转换二叉搜索树)

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 为数组长度。

maggiexie00 commented 2 years ago

思路

代码

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)
All-Sunday commented 2 years ago

思路

没得思路,看的官方题解😢。

代码

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

}

复杂度分析

ha0cheng commented 2 years ago

思路:参考官方思路,递归的形成平衡二叉树,对于一段链表来说,递归的过程就是找到中间节点,作为根节点,同时调用函数,把左右两个链表分别转化成左子树和右子树,返回左子树和右子树的根节点,作为该根节点的左右子节点即可。 注意是要把中间节点左右链表变成两个子链表需要让中间节点前一个节点断开,指向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)

XXjo commented 2 years ago

思路

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)

OmegaLzx commented 2 years ago
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;
    }
}
KesuCaso commented 2 years ago

一个函数找中点,一个函数递归构造左右子树。

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)
ZETAVI commented 2 years ago

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

bigboom666 commented 2 years ago

思路

快慢指针,分割,递归

Code

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)

taojin1992 commented 2 years ago

Idea:

use dummy head, find mid, break into halves, disconnect, recursively build the tree

Complexity:

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)

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

}
tensorstart commented 2 years ago

思路

参考第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)

duke-github commented 2 years ago

思路

分治

复杂度

时间复杂度: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;
    }
flyzenr commented 2 years ago

解题思路

用快慢指针和递归

代码


# 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)

xiayuhui231 commented 2 years ago

代码

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;

} 

};

xil324 commented 2 years ago
# 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
  1. 找到链表的中心节点,然后用同样的方法递归建立左子树和右子树。时间复杂度 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;
  2. 优化时间复杂度, 把链表转换为数组,这样查询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;
PFyyh commented 2 years ago

题目地址(109. 有序链表转换二叉搜索树)

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 为链表长度。(算不来。。)

zhishinaigai commented 2 years ago

思路

递归

代码

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;
    }
JudyZhou95 commented 2 years ago
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)
Jessie725 commented 2 years ago

Idea

Two pointer (fast & slow) to find middle node -> root Use recursion to build tree;

Code

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

Complexity

Time: O(nlogn) n for traverse, logn for binary search Space: O(n)

Yongxi-Zhou commented 2 years ago

思路

注意当只有一个节点的时候要返回这个节点。获得中间节点的值,然后分别构建左右子树。

代码

    # 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)

Venchyluo commented 2 years ago

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.

zhiyuanpeng commented 2 years ago
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)

1973719588 commented 2 years ago
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)

huiminren commented 2 years ago

题目

LC109 有序链表转换二叉搜索树

思路

首先通过快两步慢一步针的方式找到中点
递归的方式,根节点等于中点,左节点等于左子树中点,右节点等于右子树中点

代码

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)