casyup.me@outlook.com

0%

leetcode/AllNodesDistanceKinBinaryTree

All Nodes Distance K in Binary Tree

找出树中距离指定节点距离为 n 的节点

my solutions

emm…

第一种方法是制作一个映射, 其中 key 为节点值, val 为所有与 key 相邻的节点值集合.

这种方法适用于多次查询, 因为需要制作一个完整的映射表, 所以不推荐 :(

第二种是让每个节点有一个 parent, 节点便利的麻烦之处就在于他没有 parent 节点. 标准库的节点都是有 parent 节点的(除指定的 froward_list 外 = =), 足以说明有 parent 不仅对于编程, 同时对于效率也有很大提升.

但这也类似于第一种, 这种更加轻量级, 但便利寻找的时候会比第一种稍微麻烦一些.

我采用了第二种的部分概念.

仔细分析一下这个题的话, 节点相邻节点只有两种可能, 父节点和子节点. 子节点的便利非常简单, 广度优先找到同样深度的子节点就好, 问题在于父节点. 而如果找出父节点的简单规律的话, 这题也比较简单了. 假设距离为 N, 从父节点开始, 除特定子节点外的深度为 N - 1 的节点就是值的一部分, 一次类推, pp(父父)节点则是 N - 2, 直到为 0 为止, 就能遍历出所有的集.

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
class Solution {
public:
vector<int> distanceK(TreeNode* root, TreeNode* target, int K) {
stack<TreeNode*> s;
dfs(root, s, target);

vector<int> ret;
TreeNode *l = s.top();
getN(l, ret, K--);
s.pop();
while (K >= 0 && !s.empty()) {
TreeNode *c = s.top()->left == l ? s.top()->right : s.top()->left;
if (!K) {
ret.push_back(s.top()->val);
break;
}
getN(c, ret, K-- - 1);
l = s.top();
s.pop();
}

return ret;
}

void getN(TreeNode *n, vector<int>& vec, int d) {
if (!n) {
return;
} else if (!d) {
vec.push_back(n->val);
return;
}

vector<TreeNode*> t { n };
while (true) {
vector<TreeNode*> c;
for (auto v : t) {
if (v->left) {
c.push_back(v->left);
}
if (v->right) {
c.push_back(v->right);
}
}

if (!--d) {
for (auto v : c) {
vec.push_back(v->val);
}

break;
}
swap(c, t);
}

return;
}

bool dfs(TreeNode *n, stack<TreeNode*>& s, TreeNode *t) {
s.push(n);
if (!n) {
return false;
}

if (n == t) {
return true;
}

if (dfs(n->left, s, t)) {
return true;
}

s.pop();
if (dfs(n->right, s, t)) {
return true;
}

s.pop();
return false;
}
};

代码丑是丑了点 = =, 不过我其他算法也没好到哪里去… (这是必要的损失么?)

the best solution

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
class Solution {
public:
struct TreeNode2 {
int val;
TreeNode2 *left;
TreeNode2 *right;
TreeNode2 *ahead;
bool checked;
TreeNode2(int x) : val(x), left(NULL), right(NULL) ,ahead(NULL),checked(false){}
};

TreeNode2* target2;

void findahead(TreeNode* node,TreeNode2* newnode,TreeNode* target){
if (node == NULL) return;
TreeNode2 *leftnode;
TreeNode2 *rightnode;
if (newnode->val == target->val) this->target2 = newnode;
if (node->left != NULL) {
leftnode = new TreeNode2(node->left->val);
newnode->left = leftnode;
newnode->left->ahead = newnode;
}
if (node->right != NULL) {
rightnode = new TreeNode2(node->right->val);
newnode->right = rightnode;
newnode->right->ahead = newnode;
}
findahead(node->left,leftnode,target);
findahead(node->right,rightnode,target);
}

void dfs(TreeNode2* node,int step,int& k,vector<int>& res){
if (node == NULL) return;
if (node->checked == true) return;
node->checked = true;
if (k == step) res.push_back(node->val);
if (step > k) return;
dfs(node->left,step + 1,k,res);
dfs(node->right,step + 1,k,res);
dfs(node->ahead,step + 1,k,res);
}

vector<int> distanceK(TreeNode* root, TreeNode* target, int K) {
//constuct ahead
vector<int> res;
TreeNode2* newroot = new TreeNode2(root->val);
findahead(root,newroot,target);
dfs(this->target2,0,K,res);
return res;
}
};

它新建了一个节点, 其中包含 left, right, ahead 指针 :(

这会让查找变得简单, 但我并不认可这种方式 = =.