LeetCode - problem solving notes - 109 - 0109. Convert Sorted List to Binary Search Tree

Posted by webmasternovis on Tue, 02 Nov 2021 14:09:00 +0100

Solution 1

The question is 0108. Convert Sorted Array to Binary Search Tree It is possible to directly use the divide and conquer tree idea of finding the middle position as the root node in the previous question, which is to solve the method of determining the middle position in the linked list.

[refer to the official] the method to find the middle position of the linked list: the fast pointer jumps two at a time, the slow pointer jumps one at a time, the fast pointer jumps to the last (or one left), and the slow pointer is the middle position (in the case of even numbers, it is the node on the left).

In addition to the adjustment of the intermediate position, the boundary determination conditions shall also be adjusted:

  1. The right boundary is empty, only the next of the last node
  2. The backtracking condition is that the left and right pointers are the same. At this time, either the intermediate node has been constructed in the previous layer, or the right boundary is invalid
  3. The divide and conquer range changes due to the change of the definition of the right boundary
  • Time complexity: O ( n log ⁡ n ) O(n \log n) O(nlogn), where n n n is the length of the input linked list, the logarithmic time complexity of divide and conquer, and the linear complexity is found each time. Multiply the two.
  • Space complexity: O ( log ⁡ n ) O(\log n) O(logn), where n n n is the length of the input linked list and the call occupation required for backtracking.
/**
 * 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 this->makeTree(head, nullptr);
    }
    
private:
    TreeNode* makeTree(ListNode* left, ListNode* right) {
        if (left == right) {
            return nullptr;
        }
        
        auto middle = getMiddle(left, right);
        auto node = new TreeNode(middle->val);
        
        node->left = this->makeTree(left, middle);
        node->right = this->makeTree(middle->next, right);
        
        return node;
    }
    
    ListNode* getMiddle(ListNode* left, ListNode* right) {
        auto slow = left;
        auto fast = left;
        
        while (fast != right && fast->next != right) {
            fast = fast->next->next;
            slow = slow->next;
        }
        
        return slow; // In the case of an even number, it is the node on the left
    }
};

Solution 2

[official reference] actually, I used one idea before, but I forgot... It's in 0106. Construct Binary Tree from Inorder and Postorder Traversal At that time, it was just because it was found that the sequential traversal could not pass in an additional array, but use an index to mark where to go. In fact, you can save a pointer and move it backward continuously. The time of moving is adjusted to complete the creation of the leftmost node.

Why didn't you transfer this idea... Reflection.

And why does the submit take longer... Strange

  • Time complexity: O ( n ) O(n) O(n), where n n n is the length of the input linked list, the logarithmic time complexity of divide and conquer, and the length of the obtained linked list is linear complexity. Add the two.
  • Space complexity: O ( log ⁡ n ) O(\log n) O(logn), where n n n is the length of the input linked list and the call occupation required for backtracking.
/**
 * 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) {
        int length = this->getlength(head);
        now = head;
        return this->makeTree2(0, length - 1);
    }
    
private:
    ListNode* now;
	  
    TreeNode* makeTree2(int left, int right) {
        if (left > right) {
            return nullptr;
        }

        int middle = (left + right) / 2; // Select the node on the left in the middle as the root node
        auto node = new TreeNode();
        
        node->left = this->makeTree2(left, middle - 1);
        node->val = now->val;
        now = now->next;
        node->right = this->makeTree2(middle + 1, right);
        
        return node;
    }

		int getlength(ListNode* head) {
        int length = 0;
        while (head != nullptr) {
            length++;
            head = head->next;
        }
        
        return length;
    }
};

Solution 3

Python implementation of Solution 1

# 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 makeTree(left: Optional[ListNode], right: Optional[ListNode]) -> Optional[TreeNode]:
            if left == right:
                return None
            
            middle = getMiddle(left, right)
            node = TreeNode(middle.val)
            node.left = makeTree(left, middle)
            node.right = makeTree(middle.next, right)
            
            return node
        
        def getMiddle(left: ListNode, right: ListNode) -> ListNode:
            fast = left
            slow = left
            while fast != right and fast.next != right:
                fast = fast.next.next
                slow = slow.next
                
            return slow
        
        return makeTree(head, None)

Solution 4

Python implementation of Solution 2

# 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 makeTree2(left: int, right: int) -> Optional[TreeNode]:
            nonlocal now
            if left > right:
                return None

            middle = (left + right) // 2
            node = TreeNode()
            
            node.left = makeTree2(left, middle - 1)
            node.val = now.val
            now = now.next
            node.right = makeTree2(middle + 1, right)
            
            return node
        
        def getLength(head: ListNode) -> int:
            ans = 0
            while head is not None:
                ans += 1
                head = head.next
                
            return ans
        
        length = getLength(head)
        now = head
        return makeTree2(0, length - 1)

Topics: leetcode linked list Binary tree