《Cracking the Coding Interview》——第4章:树和图——题目7

2014-03-19 04:48

题目:最近公共父节点问题。

解法1:Naive算法,先对其高度,然后一层一层往上直到找到结果。

代码:

  1 // 4.7 Least Common Ancestor

  2 // This solution is Naive Algorithm, may timeout on very large and skewed trees.

  3 #include <cstdio>

  4 #include <cstring>

  5 using namespace std;

  6 

  7 const int MAXN = 10005;

  8 // tree[x][0]: parent of node x

  9 // tree[x][1]: left child of node x

 10 // tree[x][2]: right child of node x

 11 // tree[x][3]: value of node x

 12 int tree[MAXN][4];

 13 // number of nodes

 14 int e;

 15 

 16 void build(int a)

 17 {

 18     int tmp;

 19 

 20     scanf("%d", &tmp);

 21     if(tmp)

 22     {

 23         tree[a][1] = e;

 24         tree[e][3] = tmp;

 25         tree[e][0] = a;

 26         ++e;

 27         // build the left subtree

 28         build(e - 1);

 29     }

 30 

 31     scanf("%d", &tmp);

 32     if(tmp)

 33     {

 34         tree[a][2] = e;

 35         tree[e][3] = tmp;

 36         tree[e][0] = a;

 37         ++e;

 38         // build the right subtree

 39         build(e - 1);

 40     }

 41 }

 42 

 43 int main()

 44 {

 45     int n, ni;

 46     int i;

 47     // the value to be queried

 48     int m1, m2;

 49     // the corresponding node indices of m1 and m2

 50     int s1, s2;

 51     int t1, t2;

 52     int c1, c2, c;

 53 

 54     while (scanf("%d", &n)  == 1) {

 55         for (ni = 0; ni < n; ++ni) {

 56             // get value for root node

 57             e = 1;

 58             scanf("%d", &tree[0][3]);

 59 

 60             // root has no parent node

 61             tree[0][0] = -1;

 62             build(0);

 63 

 64             while (scanf("%d%d", &m1, &m2) == 2 && (m1 && m2)) {

 65                 s1 = s2 = -1;

 66                 for (i = 0;i <= e; ++i) {

 67                     if (tree[i][3] == m1) {

 68                         s1 = i;

 69                         // there're duplicate values

 70                         break;

 71                     }

 72                 }

 73                 for (i = 0;i <= e; ++i) {

 74                     if (tree[i][3] == m2) {

 75                         s2 = i;

 76                         // there're duplicate values

 77                         break;

 78                     }

 79                 }

 80 

 81                 if (s1 != -1 && s2 != -1) {

 82                     t1 = s1;

 83                     t2 = s2;

 84                     c1 = c2 = 0;

 85 

 86                     // c1 is the depth of t1

 87                     while (tree[t1][0] != -1) {

 88                         ++c1;

 89                         t1 = tree[t1][0];

 90                     }

 91                     // c2 is the depth of t2

 92                     while (tree[t2][0] != -1) {

 93                         ++c2;

 94                         t2 = tree[t2][0];

 95                     }

 96                 

 97                     // move'em to the same height level

 98                     if (c1 > c2) {

 99                         c = c1 - c2;

100                         while(c--) {

101                             s1 = tree[s1][0];

102                         }

103                     } else {

104                         c = c2 - c1;

105                         while(c--) {

106                             s2 = tree[s2][0];

107                         }

108                     }

109                 

110                     while(s1 != s2)

111                     {

112                         s1 = tree[s1][0];

113                         s2 = tree[s2][0];

114                     }

115                     printf("%d\n", tree[s1][3]);

116                 } else {

117                     // At least one value is not found in the tree.

118                     printf("Not found in the tree.\n");

119                 }

120             }

121         }

122     }

123 

124     return 0;

125 }

解法2:Naive算法的倍增优化。

代码:

  1 // 4.7 Least Common Ancestor

  2 // O(log(n)) solution with binary decomposition.

  3 #include <cstdio>

  4 #include <cstring>

  5 using namespace std;

  6 

  7 typedef struct st{

  8 public:

  9     int key;

 10     st *ll;

 11     st *rr;

 12     st(int _key = 0): key(_key), ll(NULL), rr(NULL) {}

 13 }st;

 14 

 15 // maximal number of nodes

 16 const int MAXN = 10005;

 17 // key -> node_index mapping

 18 int hash_key[MAXN];

 19 // node_index -> key mapping

 20 int key_hash[MAXN];

 21 // depth of each node

 22 int depth[MAXN];

 23 // array recording ancestors

 24 int anc[MAXN][16];

 25 // total number of nodes, index starting from 1

 26 int nc;

 27 

 28 // recursively calculate depths of nodes

 29 void getDepth(st *root, int dep)

 30 {

 31     if (root == NULL) {

 32         return;

 33     }

 34     depth[hash_key[root->key]] = dep;

 35     if (root->ll != NULL) {

 36         getDepth(root->ll, dep + 1);

 37     }

 38     if (root->rr != NULL) {

 39         getDepth(root->rr, dep + 1);

 40     }

 41 }

 42 

 43 // recursively construct a binary tree

 44 void constructBinaryTree(st *&root)

 45 {

 46     int tmp;

 47 

 48     scanf("%d", &tmp);

 49     if (tmp == 0) {

 50         root = NULL;

 51     } else {

 52         root = new st(tmp);

 53         ++nc;

 54         if (hash_key[tmp] == 0) {

 55             hash_key[tmp] = nc;

 56         }

 57         key_hash[nc] = tmp;

 58         constructBinaryTree(root->ll);

 59         constructBinaryTree(root->rr);

 60     }

 61 }

 62 

 63 // recursively initialize ancestor array

 64 void getParent(st *root)

 65 {

 66     if (root == NULL) {

 67         return;

 68     }

 69 

 70     // anc[x][0] is the direct parent of x.

 71     if (root->ll != NULL) {

 72         anc[hash_key[root->ll->key]][0] = hash_key[root->key];

 73         getParent(root->ll);

 74     }

 75     if (root->rr != NULL) {

 76         anc[hash_key[root->rr->key]][0] = hash_key[root->key];

 77         getParent(root->rr);

 78     }

 79 }

 80 

 81 // calculate LCA in O(log(n)) time

 82 int leastCommonAncestor(int x, int y)

 83 {

 84     int i;

 85 

 86     if (depth[x] < depth[y]) {

 87         return leastCommonAncestor(y, x);

 88     }

 89     for (i = 15; i >= 0; --i) {

 90         if (depth[anc[x][i]] >= depth[y]) {

 91             x = anc[x][i];

 92             if (depth[x] == depth[y]) {

 93                 break;

 94             }

 95         }

 96     }

 97     if (x == y) {

 98         return x;

 99     }

100 

101     for (i = 15; i >= 0; --i) {

102         if (anc[x][i] != anc[y][i]) {

103             // they'll finally be equal, think about the reason.

104             x = anc[x][i];

105             y = anc[y][i];

106         }

107     }

108 

109     // this is the direct parent of x

110     return anc[x][0];

111 }

112 

113 st *deleteTree(st *root)

114 {

115     if (NULL == root) {

116         return NULL;

117     }

118 

119     if (root->ll != NULL) {

120         root->ll = deleteTree(root->ll);

121     }

122     if (root->rr != NULL) {

123         root->rr = deleteTree(root->rr);

124     }

125     delete root;

126     root = NULL;

127 

128     return NULL;

129 }

130 

131 int main()

132 {

133     int ci, cc;

134     int i, j;

135     int x, y;

136     st *root;

137 

138     while (scanf("%d", &cc) == 1) {

139         for (ci = 0; ci < cc; ++ci) {

140             // data initialization 

141             memset(hash_key, 0, MAXN * sizeof(int));

142             memset(key_hash, 0, MAXN * sizeof(int));

143             memset(depth, 0, MAXN * sizeof(int));

144             memset(anc, 0, MAXN * 16 * sizeof(int));

145             nc = 0;

146             root = NULL;

147 

148             constructBinaryTree(root);

149             getParent(root);

150             getDepth(root, 1);

151             for (j = 1; j < 16; ++j) {

152                 for (i = 1; i <= nc; ++i) {

153                     anc[i][j] = anc[anc[i][j - 1]][j - 1];

154                 }

155             }

156             while (scanf("%d%d", &x, &y) == 2 && (x && y)) {

157                 if (hash_key[x] == 0 || hash_key[y] == 0) {

158                     printf("Not found in the tree.\n");

159                 } else {

160                     printf("%d\n", key_hash[leastCommonAncestor(hash_key[x], hash_key[y])]);

161                 }

162             }

163 

164             root = deleteTree(root);

165         }

166     }

167 

168     return 0;

169 }

解法3:Tarjan离线算法,并查集的妙用。

代码:

  1 // 4.7 Least Common Ancestor

  2 // Tarjan Offline Algorithm

  3 #include <cstdio>

  4 #include <cstdlib>

  5 #include <unordered_map>

  6 #include <unordered_set>

  7 using namespace std;

  8 

  9 struct TreeNode {

 10     int val;

 11     TreeNode *left;

 12     TreeNode *right;

 13     

 14     TreeNode(int _val = 0): val(_val), left(nullptr), right(nullptr) {};

 15 };

 16 

 17 void constructTree(vector<TreeNode *> &nodes, 

 18                    unordered_set<TreeNode *> &checked)

 19 {

 20     int ll, rr;

 21     int i;

 22 

 23     for (i = 0; i < (int)nodes.size(); ++i) {

 24         checked.insert(nodes[i]);

 25     }

 26     for (i = 0; i < (int)nodes.size(); ++i) {

 27         scanf("%d%d", &ll, &rr);

 28         if (ll > 0) {

 29             nodes[i]->left = nodes[ll - 1];

 30             checked.erase(nodes[ll - 1]);

 31         }

 32         if (rr > 0) {

 33             nodes[i]->right = nodes[rr - 1];

 34             checked.erase(nodes[rr - 1]);

 35         }

 36     }

 37 }

 38 

 39 TreeNode *findRoot(TreeNode *node, unordered_map<TreeNode *, TreeNode *> &disjoint_set)

 40 {

 41     if (node != disjoint_set[node]) {

 42         disjoint_set[node] = findRoot(disjoint_set[node], disjoint_set);

 43     }

 44     

 45     return disjoint_set[node];

 46 }

 47 

 48 void tarjanLCA(TreeNode *root, unordered_map<TreeNode *, TreeNode *> &disjoint_set, 

 49                unordered_map<TreeNode *, unordered_map<TreeNode *, TreeNode *> > &query, 

 50                unordered_set<TreeNode *> &checked)

 51 {

 52     if (root == nullptr) {

 53         return;

 54     }

 55     

 56     disjoint_set[root] = root;

 57     if (root->left != nullptr) {

 58         tarjanLCA(root->left, disjoint_set, query, checked);

 59         disjoint_set[root->left] = root;

 60     }

 61     if (root->right != nullptr) {

 62         tarjanLCA(root->right, disjoint_set, query, checked);

 63         disjoint_set[root->right] = root;

 64     }

 65     checked.insert(root);

 66     

 67     if (query.find(root) == query.end()) {

 68         return;

 69     }

 70     

 71     unordered_map<TreeNode *, TreeNode *>::iterator it;

 72     for (it = query[root].begin(); it != query[root].end(); ++it) {

 73         if (it->second != nullptr) {

 74             // already solved, skip it

 75             continue;

 76         }

 77         if (checked.find(it->first) != checked.end()) {

 78             query[root][it->first] = query[it->first][root] = findRoot(it->first, disjoint_set);

 79         }

 80     }

 81 }

 82 

 83 int main()

 84 {

 85     int n;

 86     int i;

 87     int val;

 88     vector<TreeNode *> nodes;

 89     TreeNode *root;

 90     unordered_map<TreeNode *, TreeNode *> disjoint_set;

 91     unordered_map<TreeNode *, unordered_map<TreeNode *, TreeNode *> > query;

 92     unordered_map<TreeNode *, unordered_map<TreeNode *, TreeNode *> >::iterator it1;

 93     unordered_set<TreeNode *> checked;

 94     unordered_map<TreeNode *, TreeNode *>::iterator it2;

 95     int idx1, idx2;

 96     

 97     while (scanf("%d", &n) == 1 && n > 0) {

 98         nodes.resize(n);

 99         for (i = 0; i < n; ++i) {

100             scanf("%d", &val);

101             nodes[i] = new TreeNode(val);

102         }

103         constructTree(nodes, checked);

104         root = *(checked.begin());

105         checked.clear();

106         

107         while (scanf("%d%d", &idx1, &idx2) == 2 && (idx1 >= 0 && idx2 >= 0)) {

108             if (idx1 > idx2) {

109                 i = idx1;

110                 idx1 = idx2;

111                 idx2 = i;

112             }

113             query[nodes[idx1]][nodes[idx2]] = nullptr;

114             query[nodes[idx2]][nodes[idx1]] = nullptr;

115         }

116         // Tarjan Offline Algorithm

117         tarjanLCA(root, disjoint_set, query, checked);

118         

119         // print the results

120         for (it1 = query.begin(); it1 != query.end(); ++it1) {

121             for (it2 = (it1->second).begin(); it2 != (it1->second).end(); ++it2) {

122                 if (it1->first->val > it2->first->val) {

123                     continue;

124                 }

125                 printf("The least common ancestor of %d and %d is %d.\n", 

126                        it1->first->val, it2->first->val, it2->second->val);

127             }

128         }

129         

130         // clear up

131         disjoint_set.clear();

132         checked.clear();

133         for (it1 = query.begin(); it1 != query.end(); ++it1) {

134             (it1->second).clear();

135         }

136         query.clear();

137     }

138     

139     return 0;

140 }

 

你可能感兴趣的:(interview)