剑指Offer - 九度1509 - 树中两个结点的最低公共祖先

剑指Offer - 九度1509 - 树中两个结点的最低公共祖先
2014-02-07 01:04
题目描述:

给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先。

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数。
其中每个测试样例包括两行,第一行为一个二叉树的先序遍历序列,其中左右子树若为空则用0代替,其中二叉树的结点个数node_num<10000。
第二行为树中的两个结点的值m1与m2(0<m1,m2<10000)。

输出:

对应每个测试案例,
输出给定的树中两个结点的最低公共祖先结点的值,若两个给定结点无最低公共祖先,则输出“My God”。

样例输入:
2

1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0

6 8

1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0

6 12
样例输出:
2

My God
题意分析:
  这道题要求将二叉搜索树转换成双向链表,我的思路是进行后序遍历。先将左右子树搞定以后,再处理根节点。
  求最近公共父节点的常用方法,有Tarjan离线算法,在线倍增法,Naive算法。
  目前我只写了Naive算法和在线倍增法的代码,结果提交后发现Naive算法通过,倍增法始终Wrong Answer。
  检查代码许久,开始怀疑数据有问题,于是在两处设置了死循环的测试代码,提交结果中果然有两处问题:
    1. 查询的节点值可能为0,也就是代表NULL的0。这个我倒是可以处理好。
    2. 二叉树中的节点值是可能有重复的,比如值为5的节点可以有很多个,那么输入5的话让我找哪个?推测倍增法出错和这个有关。
  由于这题数据有问题,所以没有继续写Tarjan版本的欲望了,很可能也AC不掉。我会在Leetcode中的对应题目附上三种方法的讲解,此处就不做详述了。
  Naive算法时间复杂度O(h),其中h为二叉树的高度,平均为O(log(n)),对于斜树来说则是O(n)。
  倍增法则用O(n * log(n))空间复杂度和O(n * log(n))预处理时间,来获取O(log(n))的稳定查询复杂度。
  1 // 690809    zhuli19901106    1509    Accepted    点击此处查看所有case的执行结果    1176KB    6753B    120MS

  2 // 201402050235

  3 // This solution is Naive Algorithm, may fail on very large skewed tree.

  4 // If you optimize it with ancestor array to achieve O(log(n)) time, you'll get WA.

  5 // Because the test data of this problem have some illegal input.

  6 #include <cstdio>

  7 #include <cstring>

  8 using namespace std;

  9 

 10 const int MAXN = 10005;

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

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

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

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

 15 int tree[MAXN][4];

 16 // number of nodes

 17 int e;

 18 

 19 void build(int a)

 20 {

 21     int tmp;

 22 

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

 24     if(tmp)

 25     {

 26         tree[a][1] = e;

 27         tree[e][3] = tmp;

 28         tree[e][0] = a;

 29         ++e;

 30         // build the left subtree

 31         build(e - 1);

 32     }

 33 

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

 35     if(tmp)

 36     {

 37         tree[a][2] = e;

 38         tree[e][3] = tmp;

 39         tree[e][0] = a;

 40         ++e;

 41         // build the right subtree

 42         build(e - 1);

 43     }

 44 }

 45 int main()

 46 {

 47     int n, ni;

 48     int i;

 49     // the value to be queried

 50     int m1, m2;

 51     // the corresponding node indices of m1 and m2

 52     int s1, s2;

 53     int t1, t2;

 54     int c1, c2, c;

 55 

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

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

 58             // get value for root node

 59             e = 1;

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

 61 

 62             // root has no parent node

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

 64             build(0);

 65 

 66             scanf("%d%d", &m1, &m2);

 67             s1 = s2 = -1;

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

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

 70                     s1 = i;

 71                     // there're duplicate values

 72                     break;

 73                 }

 74             }

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

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

 77                     s2 = i;

 78                     // there're duplicate values

 79                     break;

 80                 }

 81             }

 82 

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

 84                 t1 = s1;

 85                 t2 = s2;

 86                 c1 = c2 = 0;

 87 

 88                 // c1 is the depth of t1

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

 90                     ++c1;

 91                     t1 = tree[t1][0];

 92                 }

 93                 // c2 is the depth of t2

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

 95                     ++c2;

 96                     t2 = tree[t2][0];

 97                 }

 98                 // move'em to the same height level

 99                 if (c1 > c2) {

100                     c = c1 - c2;

101                     while(c--) {

102                         s1 = tree[s1][0];

103                     }

104                 }

105                 if (c2 > c1) {

106                     c = c2 - c1;

107                     while(c--) {

108                         s2 = tree[s2][0];

109                     }

110                 }

111                 while(s1 != s2)

112                 {

113                     s1 = tree[s1][0];

114                     s2 = tree[s2][0];

115                 }

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

117             } else {

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

119                 printf("My God\n");

120             }

121         }

122     }

123 

124     return 0;

125 }

126 

127 /*

128 // This here is my last version of code, got some strange WAs.

129 // I doubt if the test data is really legal as described.

130 // 1. m1 and m2 may be 0

131 // 2. some tree nodes may have same values, making things ambiguous.

132 // I'll prove my suspicion.

133 #include <cstdio>

134 #include <cstring>

135 using namespace std;

136 

137 typedef struct st{

138 public:

139     int key;

140     st *ll;

141     st *rr;

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

143 }st;

144 

145 // maximal number of nodes

146 const int MAXN = 10005;

147 // key -> node_index mapping

148 int hash_key[MAXN];

149 // node_index -> key mapping

150 int key_hash[MAXN];

151 // depth of each node

152 int depth[MAXN];

153 // array recording ancestors

154 int anc[MAXN][16];

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

156 int nc;

157 

158 // recursively calculate depths of nodes

159 void getDepth(st *root, int dep)

160 {

161     if (root == NULL) {

162         return;

163     }

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

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

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

167     }

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

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

170     }

171 }

172 

173 // recursively construct a binary tree

174 void constructBinaryTree(st *&root)

175 {

176     int tmp;

177 

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

179     if (tmp == 0) {

180         root = NULL;

181     } else {

182         root = new st(tmp);

183         ++nc;

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

185             hash_key[tmp] = nc;

186         }

187         key_hash[nc] = tmp;

188         constructBinaryTree(root->ll);

189         constructBinaryTree(root->rr);

190     }

191 }

192 

193 // recursively initialize ancestor array

194 void getParent(st *root)

195 {

196     if (root == NULL) {

197         return;

198     }

199 

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

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

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

203         getParent(root->ll);

204     }

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

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

207         getParent(root->rr);

208     }

209 }

210 

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

212 int leastCommonAncestor(int x, int y)

213 {

214     int i;

215 

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

217         return leastCommonAncestor(y, x);

218     }

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

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

221             x = anc[x][i];

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

223                 break;

224             }

225         }

226     }

227     if (x == y) {

228         return x;

229     }

230 

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

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

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

234             x = anc[x][i];

235             y = anc[y][i];

236         }

237     }

238 

239     // this is the direct parent of x

240     return anc[x][0];

241 }

242 

243 st *deleteTree(st *root)

244 {

245     if (NULL == root) {

246         return NULL;

247     }

248 

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

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

251     }

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

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

254     }

255     delete root;

256     root = NULL;

257 

258     return NULL;

259 }

260 

261 int main()

262 {

263     int ci, cc;

264     int i, j;

265     int x, y;

266     st *root;

267 

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

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

270             // data initialization 

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

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

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

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

275             nc = 0;

276             root = NULL;

277 

278             constructBinaryTree(root);

279             getParent(root);

280             getDepth(root, 1);

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

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

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

284                 }

285             }

286             scanf("%d%d", &x, &y);

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

288                 printf("My God\n");

289             } else {

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

291             }

292 

293             root = deleteTree(root);

294         }

295     }

296 

297     return 0;

298 }

299 */

 

你可能感兴趣的:(FF)