leetcode小结(龟速更新)

 

2017.08.20

https://leetcode.com/problems/divide-two-integers/description/

29. Divide Two Integers

Divide two integers without using multiplication, division and mod operator.

If it is overflow, return MAX_INT.

08.18面试考了这道题,采用long long类型来处理INT_MIN,对除数(divisor)右移若干位来放大一次步长,现场左移3位,回来修改如下,左移16位,22ms/4.59%。

 1 int divide(const int dividend, const int divisor) {
 2     int res = 0;
 3     int sign = 1;
 4     long long a = dividend, b = divisor, mb; /* multiple b */
 5         
 6     
 7     if ((a < 0 && b > 0) ||
 8         (a > 0 && b < 0)) {
 9         sign = -1;
10     }
11     
12     a = (a >= 0) ? a : -a;
13     b = (b >= 0) ? b : -b;
14     
15     if (1 == b) {        
16         return sign == 1 ? (a > INT_MAX ? INT_MAX : a) : -a;
17     }
18     if (a < b) {
19         return 0;
20     }
21 
22     res = 0;
23     mb = b << 16; /* 08.18: mb = b << 3;  */
24     for (a -= mb; a >= 0; a -= mb) {
25         res += 1 << 16;
26     }
27     if (a < 0) {
28         a += mb;
29         for (a -= b; a >= 0; a -= b) {
30             res++;
31         }
32     }
33 
34     return sign == 1 ? res : -res;
35 }
View Code

更好的解法应该是每次用最大的步长去减被除数(dividend)。如下代码,不依赖long long类型;先找到最大步长,然后每次循环通过右移当前步长来找到本次最大步长。

耗时为15ms/45.87%,简化循环判断条件后,时间反而增加为16ms/35.78%。

 1 int divide(const int dividend, const int divisor) {
 2     int sign = 1;
 3     int a = dividend, b = divisor, mb; /* multiple b */
 4     unsigned int ua, ub, umb;
 5     int exp;
 6     int res;
 7     
 8     if (divisor == INT_MIN) {
 9         return dividend == INT_MIN ? 1 : 0;
10     }
11 
12     if (a == INT_MIN) {
13         if ((b == -1) || (b == 1)) {
14             return b == -1 ? INT_MAX : INT_MIN;
15         }
16         a++;
17     }
18     
19     if ((a ^ b) & ~INT_MAX) {
20         sign = -1;
21     }
22     
23     a = (a >= 0) ? a : -a;
24     b = (b >= 0) ? b : -b;
25     
26     if (a <= b) {
27         return a == b ? sign : 0;
28     }
29     
30     ua = a;
31     ub = b;
32     umb = ub << 1;
33     exp = 0;
34     while (ua >= umb) {
35         exp++;
36         umb <<= 1;
37     }
38     
39     if (exp > 0) {
40         res = 1 << exp;
41         a = ua - (umb >> 1);
42         mb = umb >> 2;
43         exp--;
44 #if 1
45         /* 15ms */
46         while ((a >= b) && (mb >= b)) {
47             while (a < mb) {
48                 exp--;
49                 mb >>= 1;
50             }
51             a -= mb;
52             res += 1 << exp;
53         }
54         if (a >= b) {
55             a -= b;
56             res++;
57         }
58 #else
59         /* 16ms */
60         while (a >= b) {
61             while (a < mb) {
62                 exp--;
63                 mb >>= 1;
64             }
65             a -= mb;
66             res += 1 << exp;
67         }
68 #endif
69     }
70     else {
71         a -= b;
72         res = 1;
73     }
74     
75     if ((dividend == INT_MIN) && (a + 1 == b)) {
76         res++;
77     }
78 
79     return sign == 1 ? res : -res;
80 }
View Code

更好的解法:https://discuss.leetcode.com/topic/23206/c-8ms-solution-without-long-long

 

2017.08.16

https://leetcode.com/problems/minimum-depth-of-binary-tree/description/

111. Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

DFS (Depth First Search)

 1 int minDepth(struct TreeNode* root) {
 2     int leftMin, rightMin, min;
 3 
 4     if (root == NULL) {
 5         return 0;
 6     }
 7     leftMin = minDepth(root->left);
 8     rightMin = minDepth(root->right);
 9     if (leftMin == 0) {
10         min = rightMin;
11     }
12     else if (rightMin == 0) {
13         min = leftMin;
14     }
15     else {
16         min = leftMin < rightMin ? leftMin : rightMin;
17     }
18     return (min + 1);
19 }
View Code

耗时9ms。

看到这个解法https://discuss.leetcode.com/topic/8723/my-4-line-java-solution后,修改如下,耗时6ms。耗时节省33%的关键在于将两个if合并为一个if,可能这样生成的指令中分支较少。

int minDepth(struct TreeNode* root) {
    int leftMin, rightMin;

    if (root == NULL) {
        return 0;
    }
    leftMin = minDepth(root->left);
    rightMin = minDepth(root->right);
    if (leftMin == 0 || rightMin == 0) {
        return leftMin + rightMin + 1;
    }
    else {
        return (leftMin < rightMin ? leftMin : rightMin) + 1;
    }
}
View Code

 

BFS(Breadth First Search)

同样耗时9ms,采用类似如上修改后,耗时为6ms。我采用的不是典型的队列。

int minDepth(struct TreeNode* root) {
    struct TreeNode** nodeRow;
    int depth, len, size, i, j;
    if (root == NULL) {
        return 0;
    }
    size = 1024;
    nodeRow = malloc(sizeof(struct TreeNode*) * size);
    nodeRow[0] = root;
    len = 1;
    for (depth = 1; ; depth++){
        for (i = 0, j = len; i < len; i++) {
            if (nodeRow[i]->left == NULL) {
                if (nodeRow[i]->right == NULL) {
                    goto done;
                }
                nodeRow[i] = nodeRow[i]->right;
            }
            else {
                if (nodeRow[i]->right != NULL) {
                    if (j >= size) {
                        size *= 2;
                        nodeRow = realloc(nodeRow, sizeof(struct TreeNode*) * size);
                        /* error checking */
                    }
                    nodeRow[j++] = nodeRow[i]->right;
                }
                nodeRow[i] = nodeRow[i]->left;
            }
        }
        len = j;
    }
done:
    free(nodeRow);
    return depth;
}
View Code
int minDepth(struct TreeNode* root) {
    struct TreeNode** nodeRow;
    struct TreeNode* lChild, * rChild;
    int depth, len, size, i, j, flag;
    if (root == NULL) {
        return 0;
    }
    size = 1024;
    nodeRow = malloc(sizeof(struct TreeNode*) * size);
    nodeRow[0] = root;
    len = 1;
    j = len;
    for (depth = 1; ; depth++){
        for (i = 0; i < len; i++) {
            flag = (nodeRow[i]->left == NULL ? 0 : 2) |
                    (nodeRow[i]->right == NULL ? 0 : 1);
            switch(flag) {
            case 3:
                if (j >= size) {
                    size *= 2;
                    nodeRow = realloc(nodeRow, sizeof(struct TreeNode*) * size);
                    /* error checking */
                }
                nodeRow[j++] = nodeRow[i]->right;
                nodeRow[i] = nodeRow[i]->left;
                break;
            case 2:
                nodeRow[i] = nodeRow[i]->left;
                break;
            case 1:
                nodeRow[i] = nodeRow[i]->right;
                break;
            default: /* least probability */
                goto done;
            }
        }
        len = j;
    }
done:
    free(nodeRow);
    return depth;
}
View Code

6ms的排名是33.11% (Your time beats 33.11% of c submissions),不知道进一步如何优化。

 

2018.08 代码更新:https://github.com/albumcover/hello-world/tree/master/leetcode/algo

 

posted @ 2017-08-16 15:33  AlbumCover  阅读(179)  评论(0编辑  收藏  举报