• 剑指Offer


    剑指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
    ", tree[s1][3]);
    117             } else {
    118                 // At least one value is not found in the tree.
    119                 printf("My God
    ");
    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
    ");
    289             } else {
    290                 printf("%d
    ", key_hash[leastCommonAncestor(hash_key[x], hash_key[y])]);
    291             }
    292 
    293             root = deleteTree(root);
    294         }
    295     }
    296 
    297     return 0;
    298 }
    299 */
  • 相关阅读:
    【力扣 089】24. 两两交换链表中的节点
    【力扣 086】19. 删除链表的倒数第 N 个结点
    【力扣 085】2. 两数相加
    【力扣 093】92. 反转链表 II
    【力扣 090】25. K 个一组翻转链表
    【力扣 091】61. 旋转链表
    【力扣 088】23. 合并K个升序链表
    【力扣 087】21. 合并两个有序链表
    【力扣 092】82. 删除排序链表中的重复元素 II
    vim命令
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3539127.html
Copyright © 2020-2023  润新知