合并两个有序链表

leetcode链接

今天重做这道题, 发现之前的代码写的太糟糕了(虽然这次也一般).

刚好这一段可以用在排序链表那里.

空间复杂度为O(1).

在这道题上, 我get到的收获是这种方法的空间复杂度为O(1). 而我之前经常写创建一个新的链表, 然后这个链表上又新建一个个值, 导致复杂度为O(n). 但其实现在的O(1)的代码跟O(n)的很像, 区别在于, O(1)的不是新建值然后添加到链表, 而是直接指向旧的链表里的结点. 这样就没有额外的更多开销了.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <vector>
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int v) {
        val  = v;
        next = NULL;
    }
};

ListNode* vec2list(vector<int> vec) {
    ListNode* head  = new ListNode(0);
    ListNode* start = head;
    for (auto v : vec) {
        head->next = new ListNode(v);
        head       = head->next;
    }
    return start->next;
}

ListNode* mergeList(ListNode *left, ListNode *right) {
    ListNode *head = new ListNode(0);
    ListNode *start = head;
    while (left != NULL && right != NULL) {
        if (left->val <= right->val) {
            head->next = left;
            left = left->next;
        } else {
            head->next = right;
            right = right->next;
        }
        head = head->next;
    }
    if (left == NULL) swap(left, right);
    while (left != NULL) {
        head->next = left;
        left = left->next;
        head = head->next;
    }
    return start->next;
}

int main() {
    vector<int> vec1({1, 3, 7, 9}), vec2({0, 2, 5, 6});
    ListNode *left = vec2list(vec1), *right = vec2list(vec2);
    ListNode *newList = mergeList(left, right);
}

合并k个有序链表

k个怎么合并? 我使用了优先队列(最小堆)

首先将k个链表的头部压入队列中, 之后每次从队列中pop一个值, 然后将对应的链表的下一个值更新队列. 这样每次队列中弹出的值就是当前最小值.

维护优先队列, 队列中同时最多有k个值, 因此空间复杂度为O(k), 时间复杂度为O(nlogk)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > k_heap;
        ListNode* res = new ListNode(-1);
        ListNode* p = res;
        for (int i = 0; i < lists.size(); ++i) {
            if (lists[i] != NULL) {
                k_heap.push(make_pair(lists[i]->val, i));
                lists[i] = lists[i]->next;
            }
        }
        while (!k_heap.empty()) {
            pair<int, int> top_node = k_heap.top();
            k_heap.pop();
            p->next = new ListNode(top_node.first);
            p = p->next;
            
            if (lists[top_node.second] != NULL) {
                k_heap.push(make_pair(lists[top_node.second]->val, top_node.second));
                lists[top_node.second] = lists[top_node.second]->next;
            }
        }
        return res->next;
    }
};

排序链表

leetcode 链接

刚开始我写了一版归并排序, 空间复杂度是O(nlogn)的, 也遇到了很多的问题. 总的来说是因为自己总是遗忘一些链表的特性, 所以debug了很久.

下面是我的一些教训总结

  1. 总是把变化了的指针依然当作它的头节点指针, 然而他分明是 head = head->next 了

  2. 合并的时候想当然地把 head == NULL 当作条件, 但是其实我是在这个链表里面合并, 终止条件不是NULL, 而是另一半地起始地址

下面有些函数是来辅助debug的

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
#include <iostream>
#include <vector>
using namespace std;

struct List {
    int val;
    List* next;
    List(int v) {
        val  = v;
        next = NULL;
    }
};

void list2vec(List* head, int len) {
    vector<int> debug_vec;
    int i = 0;
    while (i < len) {
        debug_vec.push_back(head->val);
        cout << head->val << " ";
        head = head->next;
        i++;
    }
    cout << endl;
}

List* listSort(List* mylist, int len) {
    if (len == 0) return NULL;
    if (len == 1) return mylist;
    if (mylist == NULL) return NULL;
    if (mylist->next == NULL) return mylist;
    int mid    = len / 2;
    List* head = mylist;
    List *preMylist = mylist, *preHead = head;
    int i      = 0;
    while (i < mid) {
        i++;
        head = head->next;
    }
    mylist = listSort(mylist, mid);
    head = listSort(head, len - mid);
    List* newList = new List(0);
    List* newHead = newList;

    int left = mid, right = len - mid;
    int x = 0, y = 0;

    while (x < left && y < right) {
        if (head->val <= mylist->val) {
            newList->next = new List(head->val);
            newList       = newList->next;
            head          = head->next;
            y += 1;
        } else {
            newList->next = new List(mylist->val);
            newList       = newList->next;
            mylist        = mylist->next;
            x += 1;
        }
    }

    if (x == left && y != right) {
        while (y < right) {
            newList->next = new List(head->val);
            newList       = newList->next;
            head          = head->next;
            y++;
        }
    } else if (x != left && y == right) {
        while (x < left) {
            newList->next = new List(mylist->val);
            newList       = newList->next;
            mylist        = mylist->next;
            x++;
        }
    }

    mylist = newHead->next;
    list2vec(mylist, len);
    return mylist;
}

List* vec2list(vector<int> vec) {
    List* head  = new List(0);
    List* start = head;
    for (auto v : vec) {
        head->next = new List(v);
        head       = head->next;
    }
    return start->next;
}

int main() {
    vector<int> vec({4, 3, 8, 1, 2, 7, 9, 0, 5});
    List* head = vec2list(vec);
    head       = listSort(head, vec.size());
    while (head != NULL) {
        cout << head->val << ' ';
        head = head->next;
    }
    cout << endl;
}

又写了一版空间复杂度O(1)的. 这个版本中使用快慢指针法将链表分割为两段. 使用了合并有序链表相同的代码段.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
/**
 * 空间复杂度O(1)的版本
 */

#include <iostream>
#include <vector>
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int v) {
        val  = v;
        next = NULL;
    }
};

void list2vec(ListNode* head) {
    vector<int> debug_vec;
    while (head != NULL) {
        debug_vec.push_back(head->val);
        cout << head->val << " ";
        head = head->next;
    }
    cout << endl;
}

ListNode* mergeList(ListNode* left, ListNode* right) {
    ListNode* head  = new ListNode(0);
    ListNode* start = head;
    while (left != NULL && right != NULL) {
        if (left->val <= right->val) {
            head->next = left;
            left       = left->next;
        } else {
            head->next = right;
            right      = right->next;
        }
        head = head->next;
    }
    if (left == NULL) swap(left, right);
    while (left != NULL) {
        head->next = left;
        left = left->next;
        head = head->next;
    }
    return start->next;
}

ListNode* listSort(ListNode* mylist) {
    if (mylist == NULL) return NULL;
    if (mylist->next == NULL) return mylist;
    // 快慢指针法求中点
    ListNode *slow = mylist, *fast = mylist->next, *last = NULL;
    while (fast != NULL) {
        last = slow;
        slow = slow->next;
        if (fast->next != NULL)
            fast = fast->next->next;
        else
            fast = fast->next;
    }
    // 分割链表
    if (last != NULL) {
        last->next = NULL;
    }
    ListNode *left = mylist, *right = slow;

    left  = listSort(left);
    right = listSort(right);

    list2vec(left);
    list2vec(right);

    ListNode *newList = mergeList(left, right);
    
    return newList;
}

// 快速构造链表的方法
ListNode* vec2list(vector<int> vec) {
    ListNode* head  = new ListNode(0);
    ListNode* start = head;
    for (auto v : vec) {
        head->next = new ListNode(v);
        head       = head->next;
    }
    return start->next;
}

int main() {
    vector<int> vec({4, 3, 8, 1, 2, 7, 9, 0, 5});
    ListNode* head = listSort(vec2list(vec));
    cout << "order:\n";
    while (head != NULL) {
        cout << head->val << ' ';
        head = head->next;
    }
    cout << endl;
}

分隔链表

leetcode链接

编写程序以 x 为基准分割链表,使得所有小于 x 的节点排在大于或等于 x 的节点之前。如果链表中包含 x,x 只需出现在小于 x 的元素之后(如下所示)。分割元素 x 只需处于“右半部分”即可,其不需要被置于左右两部分之间。

1
2
输入: head = 3->5->8->5->10->2->1, x = 5
输出: 3->1->2->10->5->5->8

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/partition-list-lcci 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题虽然是中等题, 但其实很简单. 初看还以为是类似快排的分割, 再看没想到更简单.

只需要将所有比x小的数移出来, 建立新的链表, 然后再连接原链表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
// 只需要将所有比x小的数移出来, 建立新的链表, 然后再连接原链表
    ListNode* partition(ListNode* head, int x) {
        ListNode *start = new ListNode(-1);
        start->next = head;
        ListNode *last = start, *now = head;
        ListNode *less = new ListNode(-1);
        ListNode *headLess = less;
        while (now != NULL) {
            if (now->val >= x) {
                now = now->next;
                last = last->next;
            } else {
                less->next = now;
                now = now->next;
                last->next = now;
                less = less->next;
            }
        }
        less->next = start->next;
        return headLess->next;
    }
};

倒数第k个结点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2.

返回链表 4->5.

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题还挺有意思, 要想知道倒数第k个结点, 只需要用两个指针, 第一个先走k步, 然后同步走. 慢的那个最后就是倒数第k个结点了.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution {
public:
    ListNode* getKthFromEnd(ListNode* head, int k) {
        ListNode *start = new ListNode(0);
        start->next = head;
        ListNode *slow = start, *fast = start;
        for (int i = 0; i < k; i++) {
            fast = fast->next;
        }
        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }
};

环形链表

leetcode链接

这道题只需要判断是否有环, 而不需要判断环入口的地址.

一道非常经典的题目, 双指针的方法比较妙. 有多种解法.

  1. hashTable解法. hashTable的复杂度为O(1)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        bool hasCycle(ListNode *head) {
            unordered_map<ListNode*, int> addr;
            while (head != NULL) {
                if (addr[head] == 1) return true;
                addr[head] = 1;
                head = head->next;
            }
            return false;
        }
    };
    
  2. 双指针(快慢指针)解法: 一个一次走一步, 一个一次走两步, 走到他们的值(指向的地址值)相等了, 那就是有环了.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    class Solution {
    public:
        bool hasCycle(ListNode *head) {
            ListNode *slow = head, *fast = head;
            while (fast != NULL) {
                slow = slow->next;
                if (fast->next == NULL) return false;
                fast = fast->next->next;
                if (slow == fast) return true;
            }
            return false;
        }
    };
    

环形链表2

leetcode链接

这个环形链表要求找出是第一个结点是环的开始(也就是tail结点指向的结点)

同样的可以用hashTable来做, 就不放代码了.

这道题用双指针法非常妙. 方法就是, 当快慢指针相遇之后, 将快指针放到开头, 然后同时一步一步向前, 第二次相遇点就是他们环的起点了.

这篇题解很好地证明了原因

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head, *slow = head;
        while (fast != NULL) {
            if (fast->next == NULL) return NULL;
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) break;
        }
        if (fast == NULL) return NULL;
        fast = head;
        while (fast != slow) {
            fast = fast->next;
            slow = slow->next;
        }
        return fast;
    }
};

删除排序链表中的重复元素

leetcode链接

一道简单题, 链表是有序的. 主要考察一些链表的操作.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode *start = new ListNode(-1);
        start->next = head;
        ListNode *last = start, *now = head;
        while (now != NULL) {
            if (now->next != NULL) {
                if (now->val == now->next->val) {
                    last->next = now->next;
                } else {
                    last = now;
                }
            }
            now = now->next;
        }
        return start->next;
    }
};

删除排序链表中的重复元素2

leetcode链接

和上一题的区别是, 如果一个数重复出现了, 那么全部删掉, 一个都不保留

只需要加一个flag标志, 表示是否是重复的元素. 如果是, 那么在到达下一个新的值的结点的时候删除这个结点.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode *start = new ListNode(-1);
        start->next = head;
        ListNode *last = start, *now = head;
        bool flag = false;  // 表示重复标志
        while (now != NULL) {
            if (now->next != NULL) {
                if (now->val == now->next->val) {
                    last->next = now->next;
                    flag = true;
                } else {
                    if (flag) last->next = now->next;
                    else last = now;
                    flag = false;
                }
            } else if (flag) {
                last->next = NULL;
            }
            now = now->next;
        }
        return start->next;
    }
};

奇偶链表

leetcode链接

分别建立奇数偶数的头部, 然后指向奇数和偶数索引的结点.

需要注意在偶数结束的时候, 要将它的最后一个结点指向NULL. 否则会形成环.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        ListNode *ji = new ListNode(-1), *ou = new ListNode(-1);
        ListNode *preJi = ji, *preOu = ou;
        int i = 0;
        while (head != NULL) {
            i += 1;
            if (i % 2) {
                ji->next = head;
                ji = ji->next;
            } else {
                ou->next = head;
                ou = ou->next;
            }
            head = head->next;
        }
        ou->next = NULL;
        ji->next = preOu->next;
        return preJi->next;
    }
};

重排链表

给定一个单链表 L:L0→L1→…→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3. 示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/reorder-list 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

把所有链表结点的值存到vector中, 然后两个指针, 一个从头一个从尾, 分别遍历过来.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
    void reorderList(ListNode* head) {
        if (head == NULL) return;
        ListNode *iter = head;
        vector<ListNode*> ps;
        while (iter != NULL) {
            ps.push_back(iter);
            iter = iter->next;
        }
        debug_list(head);
        int a = 0, b = ps.size() - 1;
        while (a < b) {
            ps[b]->next = ps[a]->next;
            ps[a]->next = ps[b];
            a++;
            b--;
        }
        ps[a]->next = NULL;
        debug_list(head);
    }
};

或者也可以将链表分为左右两半, 然后第二半调用反转链表的方法, 之后合并.

反转链表

这种题是真的烦, 操作太细节了.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == NULL) return NULL;
        if (head->next == NULL) return head;
        ListNode *toBeZero = head;
        ListNode* start = new ListNode(0);
        start->next = head;
        ListNode* pos = head->next;
        while (pos != NULL) {
            ListNode *tmp = pos->next;
            pos->next = start->next;
            start->next = pos;
            pos = tmp;
        }
        head->next = NULL;
        return start->next;
    }
};

反转链表2

[leetcode链接

遍历找出在[m, n]位置的链表, 然后拆分成三段, 调用反转链表函数反转这部分, 再拼接起来.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Solution {
   public:
    ListNode *reverseBetween(ListNode *head, int m, int n) {
        if (head == NULL) return NULL;
        int ind       = 0;
        ListNode *start = new ListNode(0);
        start->next = head;
        ListNode *sub = start, *ano = NULL, *last, *next, *last0;
        while (sub != NULL) {
            if (ind == m - 1) last0 = sub;
            if (ind == m) {
                ano = sub;
            }
            if (ind == n) {
                last = sub;
                next = last->next;
                break;
            }
            ind++;
            sub = sub->next;
        }
        last->next = NULL;
        ListNode *newSub = reverseList(ano);
        last0->next = newSub;
        ano->next = next;
        return start->next;
    }

    // 反转链表
    ListNode *reverseList(ListNode *head) {
        if (head == NULL) return NULL;
        if (head->next == NULL) return head;
        ListNode *toBeZero = head;
        ListNode *start    = new ListNode(0);
        start->next        = head;
        ListNode *pos      = head->next;
        while (pos != NULL) {
            ListNode *tmp = pos->next;
            pos->next     = start->next;
            start->next   = pos;
            pos           = tmp;
        }
        head->next = NULL;
        return start->next;
    }
};

k个一组反转链表

没有按题目要求做到O(1)的空间复杂度, 而是用了vector做辅助.

先将所有结点存起来, 然后分别反转, 再连接起来.

要用到O(1)的空间太细节了啊, debug好久做不出来.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
   public:
    ListNode *reverseKGroup(ListNode *head, int k) {
        if (head == NULL) return NULL;
        ListNode *pos = head;
        vector<ListNode *> ps, allPs;
        while (pos != NULL) {
            ps.push_back(pos);
            pos = pos->next;
            if (ps.size() == k) {
                int x = 0, y = ps.size() - 1;
                while (x < y) {
                    swap(ps[x], ps[y]);
                    x++, y--;
                }
                allPs.insert(allPs.end(), ps.begin(), ps.end());
                ps.clear();
            }
        }
        allPs.insert(allPs.end(), ps.begin(), ps.end());
        
        ListNode *start = new ListNode(0), *loc = start;
        for (auto p : allPs) {
            loc->next = p;
            loc       = loc->next;
        }
        allPs.back()->next = NULL;
        return start->next;
    }
};

有序链表转二叉树

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

给定的有序链表: [-10, -3, 0, 5, 9],

一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:

      0
     / \
   -3   9
   /   /
 -10  5

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题的重点在于保持二叉搜索树高度平衡.

刚开始没有严格考虑这一条件, 就直接按照模拟中序遍历的方式, 自底向上地建立搜索树.

后来发现这样会断层, 于是引入了count, 没有剩余可扩展节点了就停止扩展, 而不是一直往最深入扩展. 但是还是错了, 因为树不平衡. 之前count是到它的左子树-1, 右子树-1, 考虑到平均分配, 就给左子树cnt/2, 右子树cnt – 1 - cnt/2.

下面是实现的代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
   public:
	TreeNode *sortedListToBST(ListNode *head) {
		if (head == NULL) return NULL;
		int cnt       = 0;
		ListNode *pos = head;
		while (pos != NULL) {
			cnt += 1;
			pos = pos->next;
		}

		TreeNode *ans = build(head, cnt);
		return ans;
	}

	TreeNode *build(ListNode *&head, int cnt) {
		if (head == NULL) return NULL;
		if (cnt <= 0) return NULL;
		int nowCnt     = cnt;
		int leftCnt = nowCnt / 2;
		int rightCnt = nowCnt - 1 - leftCnt;
		TreeNode *left = build(head, leftCnt);
		TreeNode *root = new TreeNode(head->val);
		head            = head->next;
		TreeNode *right = build(head, rightCnt);
		root->left      = left;
		root->right     = right;
		return root;
	}
};

我这个方法在官方题解中属于中序遍历模拟方法.