4.26LeetCode

590. N-ary Tree Postorder Traversal

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
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;

Node() {}

Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public:
vector<int> postorder(Node* root) {
vector<int> res;
help(root,res);
return res;
}
void help(Node* p,vector<int>& res){
if(!p) return ;
for(auto i:p->children)
help(i,res);
res.push_back(p->val);
}
};

解法二:迭代我们也可以使用迭代的方法来做,这里有个小trick,写法跟先序遍历十分的像,不同的就是每次把从stack中取的结点的值都加到结果res的最前面,还有就是遍历子结点数组的顺序是正常的顺序,而前序遍历是从子结点数组的后面往前面遍历,这点区别一定要注意。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
vector<int> postorder(Node* root) {
vector<int> res;
help(root,res);
return res;
}
void help(Node* p,vector<int>& res){
if(!p) return ;
for(auto i:p->children)
help(i,res);
res.push_back(p->val);
}
};

429. N-ary Tree Level Order Traversal

层次遍历,没啥好说的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> res;
if(!root) return res;
deque<Node*> temp;
temp.push_back(root);
while(!temp.empty()){
int size=temp.size();
vector<int> t;
for(int i=0;i<size;i++){
auto it=temp.front();
temp.pop_front();
t.push_back(it->val);
for(auto j:it->children)
temp.push_back(j);
}
res.push_back(t);
t.clear();
}
return res;
}
};

559. Maximum Depth of N-ary Tree

  1. N叉树的最大深度

递归非常简单。。没啥好说的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int maxDepth(Node* root) {
int res=0;
help(root,0,res);
return res;
}

void help(Node* p,int s,int& res) {
if(!p) return;
s++;
res=s>res? s:res;
for(auto it:p->children)
help(it,s,res);
}
};

208. Implement Trie (Prefix Tree)

比较简单的medium题了,就是比较繁琐。在定义前缀树的时候要先去检查是否已经存在该结点。感觉还是对map的使用不够熟练。

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
class Node {
public:
bool isWord=false;
unordered_map<char,Node*> next;
Node() {
isWord=false;
}
Node(unordered_map<char,Node*> _next){
next=_next;
isWord=false;
}
};
class Trie {
public:
Node* root;
/** Initialize your data structure here. */
Trie() {
root=new Node();
}

/** Inserts a word into the trie. */
void insert(string word) {
Node* temp=root;
for(int i=0;i<word.length();i++){
auto it=temp->next.find(word[i]);
if(it==temp->next.end()){
temp->next[word[i]]=new Node();
temp=temp->next[word[i]];
}else temp=temp->next[word[i]];

}
temp->isWord=true;
}

/** Returns if the word is in the trie. */
bool search(string word) {
Node* temp=root;
for(int i=0;i<word.length();i++){
auto it=temp->next.count(word[i]);
if(!it) return false;
temp=temp->next[word[i]];
}
if(temp->isWord) return true;
return false;
}

/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
Node* temp=root;
for(int i=0;i<prefix.length();i++){
if(temp->next.count(prefix[i])==0) return false;
temp=temp->next[prefix[i]];
}
return true;
}
};

677. Map Sum Pairs

  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
    class Node{
    public:
    int num=0;
    unordered_map<char,Node*> next;
    Node() {}
    Node(unordered_map<char,Node*> _next){
    next=_next;
    }
    };
    class MapSum {
    public:
    Node *root;
    /** Initialize your data structure here. */
    MapSum() {
    root=new Node();
    }

    void insert(string key, int val) {
    Node *temp=root;
    for(int i=0;i<key.length();i++){
    auto it=temp->next.find(key[i]);
    if(it==temp->next.end()){
    temp->next[key[i]]=new Node();
    temp=temp->next[key[i]];
    }
    else temp=temp->next[key[i]];
    }
    temp->num=val;
    }

    int sum(string prefix) {
    Node *temp=root;
    for(int i=0;i<prefix.length();i++){
    auto it=temp->next.find(prefix[i]);
    if(it==temp->next.end()) return 0;
    else temp=temp->next[prefix[i]];
    }
    return help(temp);
    }

    int help(Node *p){
    int sum=p->num;
    for(auto it=p->next.begin();it!=p->next.end();it++)
    sum+=help(it->second);
    return sum;
    }
    };

648. Replace Words

  1. 单词替换
    写得有些自闭,不想说话。逻辑不难,主要是对于C++中string类的运用暂时还有所欠缺,特别对于一个长句子的处理。
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
class Node {
public:
bool isWord=false;
unordered_map<char,Node*> next;
Node() {
isWord=false;
}
Node(unordered_map<char,Node*> _next){
next=_next;
isWord=false;
}
};
class Trie {
public:
Node* root;
/** Initialize your data structure here. */
Trie() {
root=new Node();
}

/** Inserts a word into the trie. */
void insert(string word) {
Node* temp=root;
for(int i=0;i<word.length();i++){
auto it=temp->next.find(word[i]);
if(it==temp->next.end()){
temp->next[word[i]]=new Node();
temp=temp->next[word[i]];
}else temp=temp->next[word[i]];

}
temp->isWord=true;
}

/** Returns if the word is in the trie. */
bool search(string word) {
Node* temp=root;
for(int i=0;i<word.length();i++){
auto it=temp->next.count(word[i]);
if(!it) return false;
temp=temp->next[word[i]];
}
if(temp->isWord) return true;
return false;
}

/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
Node* temp=root;
for(int i=0;i<prefix.length();i++){
if(temp->next.count(prefix[i])==0) return false;
temp=temp->next[prefix[i]];
}
return true;
}
};
class Solution {
public:
string replaceWords(vector<string>& dict, string sentence) {
Trie tire;
vector<string> temp;
for(string it:dict) tire.insert(it);
int i=0;
string t;
for(int i=0;i<sentence.length();i++){
if(sentence[i]!=' ') {
t+=sentence[i];
}
else{
temp.push_back(t);
t.clear();
}
}
temp.push_back(t);
for(int it=0;it<temp.size();it++){
Node *p=tire.root;
string repre;
for(int i=0;i<temp[it].length();i++){
if(p->isWord){
temp[it]=repre;
break;
}
auto it1=p->next.find(temp[it][i]);

if(it1!=p->next.end()){
p=p->next[temp[it][i]];
}
else break;
repre+=temp[it][i];
}
repre.clear();
}
string res=temp[0];
for(int i=1;i<temp.size();i++)
res+=' '+temp[i];
return res;
}
};

4.25LeetCode

总结: 昨天晚上被蚊子咬到睡不着觉,好不容易进入梦乡,恍惚间又听到噗通一声,我当时就料想到是手机掉到床柜后面去了,于是早上七点多钟又爬起来翻箱倒柜找手机关闹钟。
所以意料当中地今天上午下午摸鱼只做了三条题目,都是比较ez的,晚上划水搭建了下博客。

701. Insert into a Binary Search Tree

Given the root node of a binary search tree (BST) and a value to be inserted into the tree, insert the value into the BST. Return the root node of the BST after the insertion. It is guaranteed that the new value does not exist in the original BST.

Note that there may exist multiple valid ways for the insertion, as long as the tree remains a BST after insertion. You can return any of them.

For example,

Given the tree:

    4
   / \
  2   7
 / \
1   3

And the value to insert: 5

You can return this binary search tree:

     4
   /   \
  2     7
 / \   /
1   3 5

This tree is also valid:

     5
   /   \
  2     7
 / \   
1   3
     \
      4

解答:
方案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
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(!root) return new TreeNode(val);
if(val > root->val){
if(root->right==nullptr) root->right=new TreeNode(val);
else insertIntoBST(root->right,val);
}
else if(val < root->val){
if(root->left==nullptr) root->left=new TreeNode(val);
else insertIntoBST(root->left,val);
}
return root;
}
};

方案2 迭代求解,用时明显短于递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(!root) return new TreeNode(val);
TreeNode *p=root;
while(1){
if(val<p->val&&p->left)
p=p->left;
else if(val>p->val&&p->right)
p=p->right;
else break;
}
if(p->val <val) p->right=new TreeNode(val);
else p->left=new TreeNode(val);
return root;
}
};

原题中特地强调,可以改变树的结构,但是相对来说比较复杂,翻了翻评论区并没有这么写的解答,我思考了下,感觉与平衡二叉树的删除类似,在找到其应该插入位置后根据是否存在左右子树分类谈论。二叉树实在是太复杂啦!

235. Lowest Common Ancestor of a Binary Search Tree

  1. 二叉搜索树的最近公共祖先
    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]

Example 1:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation: The LCA of nodes 2 and 8 is 6.

Example 2:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

Note:

All of the nodes’ values will be unique.
p and q are different and both values will exist in the BST.

解法: 递归实在是太好写啦,主要注意其二叉搜索树的特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root) return nullptr;
if(p->val<root->val && q->val>root->val) return root;
if(p->val>root->val && q->val<root->val) return root;
if(p==root||q==root) return root;
if(p->val<root->val && q->val<root->val) return lowestCommonAncestor(root->left,p,q);
if(p->val>root->val && q->val>root->val) return lowestCommonAncestor(root->right,p,q);
return root;
}
};

589. N-ary Tree Preorder Traversal

  1. N叉树的前序遍历

一开始写了个递归版本,发现速度很慢,想写迭代版本,但是感觉和二叉树又不太一样 参考了下评论区大神的思路 豁然开朗 随便写写写下来,
发现时间还是特别高! 非常生气地拿了80ms的源码来跑,结果虽然比我的好,还是很高。 就有点懵逼了。

感觉这个迭代写法还是可以学习一下,和之前常写的二叉树的前序遍历迭代版本不太相同。(对栈的使用)

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
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;

Node() {}

Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
*/
// class Solution {
// public:
// vector<int> preorder(Node* root) {
// vector<int> res;
// help(root,res);
// return res;
// }
// void help(Node* p,vector<int>& res){
// if(!p) return;
// res.push_back(p->val);
// for(auto it:p->children)
// help(it,res);
// }
// };

// class Solution {
// public:
// vector<int> preorder(Node* root) {
// stack<Node*> stk;
// vector<int> res;
// if(!root) return res;
// Node* p=root;
// stk.push(p);
// while(!stk.empty()){
// p=stk.top();stk.pop();
// res.push_back(p->val);
// if(p->children.empty())
// continue;
// else{
// for(auto it=p->children.rbegin();it!=p->children.rend();it++)
// stk.push(*it);
// }
// }
// return res;


// }
// };



class Solution {
public:
vector<int> preorder(Node* root) {
vector<int> res;
if(root == nullptr) return res;

stack<Node*> st;

st.push(root);

while(!st.empty())
{
Node* t = st.top();
st.pop();
res.push_back(t->val);
for(auto r = t->children.rbegin(); r != t->children.rend(); r++)
{
st.push(*r);
}
}

return res;
}
};

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×