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:
- The right boundary is empty, only the next of the last node
- 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
- 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)