forked from azl397985856/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 每日一题 - 2019-09-16 and 2019-08-21 (azl397985856#181)
版本号比较 and 黑白球
- Loading branch information
1 parent
b2af572
commit d851a0e
Showing
2 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# 毎日一题 - 桶中取黑白球 | ||
|
||
## 信息卡片 | ||
|
||
* 时间:2019-08-21 | ||
* tag:`Math` `位运算` | ||
## 题目描述 | ||
``` | ||
有一个桶,里面有白球,黑球各100个,你必须用以下规则将球取出来: | ||
- 每次从桶里取两个球 | ||
- 如果两个球是相同的颜色,那么再放一个黑球 | ||
- 如果两个球是不同的颜色,那么再放一个白球。 | ||
问:最后一个球是黑球的概率是多少? | ||
``` | ||
|
||
## 参考答案 | ||
|
||
### 1. 数学分析原问题 | ||
|
||
首先我们来仔细读题看看我们有哪些知道的信息: | ||
|
||
- 不管什么情况,每次球的总数减1; | ||
- 两黑:黑球-1,白球0; | ||
- 两白:黑球+1,白球-2; | ||
- 一黑一白:黑球-1,白球0; | ||
- 最后两球只要不是一黑一白,最后一球都是黑; | ||
|
||
初始状态是100个黑球和100个白球,从上面三个状态可知道,黑球要么+1要么-1,而白球要么不变要么-2;在198次取球后,我们可知剩余两个球,现在假设剩余的两球为一黑一白,可以证明这是不存在的。 | ||
|
||
因为白球下降是以2的倍数下降,不可能从100下降至1,;故剩余两球肯定不是一黑一白的情况,那么最后一球的情况必然为黑。 | ||
|
||
|
||
### 2. 原问题拓展(n个黑球和m个白球) | ||
|
||
在n+m-2次取球后,剩余两个球。 | ||
|
||
由于我们知道白球数下降是以2的倍数下降,如果m为偶数的话,是不可能下降至1;即同上1,最后一球必为黑球。如果m为奇数的话,最后必然是k黑1白(k>=1),显然对于任意的k,要么剩余全是黑球,要么黑球不断减1,最后变为1黑1白。全黑和1黑1白最后的结果都是剩余一个白球。 | ||
|
||
得出结论,最后一球结果无关黑球数量(n>=0),仅与白球数量m有关。 | ||
|
||
- 如果白球m为奇数,最后一球必然白; | ||
- 如果白球m为偶数,最后一球必然黑; | ||
|
||
### 3. 抽象为数学模型,严格证明 | ||
|
||
不妨设黑球为0,白球为1; | ||
|
||
- 两黑:F(0,0) = 0;表示两个黑球生一黑; | ||
- 两白:F(1,1) = 0;表示两个白球生一黑; | ||
- 一黑一白:F(0,1) = 0;表示一个黑球一个白球生一白; | ||
|
||
仔细观察就会发现这个函数F就是XOR(异或); | ||
|
||
那么m个黑球和n个白球,就抽象为m个0和n个1作异或的结果;而且我们可知异或满足结合律和交换律(证明略,最简单的证明方法枚举)。 | ||
|
||
那么问题就很简单,对于任意多0,异或结果依然是0,所以对于任意多1,只需要考虑1个数的奇偶性就可判断最后剩余1个1还是0个1; | ||
|
||
结论同2: | ||
|
||
- 1(白球)的个数奇数,最后异或结果为1; | ||
- 1(白球)的个数偶数,最后异或结果为0; | ||
|
||
|
||
## 优秀解答 | ||
|
||
>暂缺 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
# 毎日一题 - 版本号比较 | ||
|
||
## 信息卡片 | ||
|
||
* 时间:2019-09-16 | ||
* 题目链接:<https://leetcode-cn.com/problems/compare-version-numbers/> | ||
* tag:`String` | ||
## 题目描述 | ||
``` | ||
比较两个版本号 version1 和 version2。 | ||
如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回 0。 | ||
你可以假设版本字符串非空,并且只包含数字和 . 字符。 | ||
. 字符不代表小数点,而是用于分隔数字序列。 | ||
例如,2.5 不是“两个半”,也不是“差一半到三”,而是第二版中的第五个小版本。 | ||
你可以假设版本号的每一级的默认修订版号为 0。例如,版本号 3.4 的第一级(大版本)和第二级(小版本)修订号分别为 3 和 4。其第三级和第四级修订号均为 0。 | ||
示例 1: | ||
输入: version1 = "0.1", version2 = "1.1" | ||
输出: -1 | ||
示例 2: | ||
输入: version1 = "1.0.1", version2 = "1" | ||
输出: 1 | ||
示例 3: | ||
输入: version1 = "7.5.2.4", version2 = "7.5.3" | ||
输出: -1 | ||
示例 4: | ||
输入:version1 = "1.01", version2 = "1.001" | ||
输出:0 | ||
解释:忽略前导零,“01” 和 “001” 表示相同的数字 “1”。 | ||
示例 5: | ||
输入:version1 = "1.0", version2 = "1.0.0" | ||
输出:0 | ||
解释:version1 没有第三级修订号,这意味着它的第三级修订号默认为 “0”。 | ||
提示: | ||
版本字符串由以点 (.) 分隔的数字字符串组成。这个数字字符串可能有前导零。 | ||
版本字符串不以点开始或结束,并且其中不会有两个连续的点。 | ||
``` | ||
|
||
## 参考答案 | ||
|
||
### 1. 递归解决 | ||
|
||
其实这个问题其实简化后就是依次比较每一个修订版本大小,所以问题有以下几点: | ||
|
||
1. 获取每个修订版本号大小; | ||
2. 处理每个修订版本号前导零问题; | ||
3. 处理不同版本有不同次数修订版本; | ||
|
||
问题1:这个如果对字符串处理比较熟悉的会比较简单,直接遍历循环找到第一个逗号first_dot(找不到的情况设为-1),str.substr(0, first_dot)即可。针对第二,第三个逗号,我们用递归的方案回避,这样每次我们都相当于找第一个逗号前的数字。 | ||
|
||
问题2:前导零问题更容易解决,在遍历过程中找到第一个非零数first_no_zero,str.substr(first_no_zero, first_dot - first_no_zero)。当然更简单的方案是定义初值v1 = 0,每次计算v1 = v1*10 + str[i] - 'a' | ||
|
||
问题3:针对不同次数的修订版本,我们可以在字符串末尾填0表示。即有一个版本号first_dot = -1。 | ||
|
||
代码如下: | ||
|
||
```c++ | ||
class Solution { | ||
public: | ||
int first_num(string str, int& first_dot){ | ||
int v1 = 0; | ||
first_dot = -1; | ||
for(int i = 0; i < str.size(); i++){ | ||
if(str[i] == '.'){ | ||
first_dot = i; | ||
break; | ||
} | ||
else | ||
v1 = v1 * 10 + (str[i] - '0'); | ||
} | ||
return v1; | ||
} | ||
|
||
int compareVersion(string version1, string version2) { | ||
int v1 = 0, v2 = 0; | ||
int v1_first_dot, v2_first_dot; | ||
v1 = first_num(version1, v1_first_dot); | ||
v2 = first_num(version2, v2_first_dot); | ||
if(v1 > v2) | ||
return 1; | ||
else if(v1 < v2) | ||
return -1; | ||
else{ | ||
if(v1_first_dot == -1 && v2_first_dot == -1) | ||
return 0; | ||
if(v1_first_dot == -1) | ||
version1 = "0"; | ||
else | ||
version1 = version1.substr(v1_first_dot+1); | ||
if(v2_first_dot == -1) | ||
version2 = "0"; | ||
else | ||
version2 = version2.substr(v2_first_dot+1); | ||
return compareVersion(version1, version2); | ||
} | ||
} | ||
}; | ||
|
||
``` | ||
### 2. 数组 | ||
解析每个版本号,放入数组,依次比较大小。 | ||
```c | ||
int compareVersion(char * version1, char * version2){ | ||
if (version1 == NULL || version2 == NULL) return -1; | ||
int *val1 = (int *)calloc(1024, sizeof(int)); | ||
int *val2 = (int *)calloc(1024, sizeof(int)); | ||
int len1 = strlen(version1), top1 = 0; | ||
int len2 = strlen(version2), top2 = 0; | ||
int i, n; | ||
for (i = 0, n = 0; i < len1; ++i) { //解析版本1 | ||
if (version1[i] == '.') { | ||
val1[top1++] = n; | ||
n = 0; | ||
}else n = n*10 + (version1[i] & 0x0f); | ||
} | ||
val1[top1++] = n; | ||
for (i = 0, n = 0; i < len2; ++i) { //解析版本1 | ||
if (version2[i] == '.') { | ||
val2[top2++] = n; | ||
n = 0; | ||
}else n = n*10 + (version2[i] & 0x0f); | ||
} | ||
val2[top2++] = n; | ||
for (i = 0; i < top1 && i < top2; ++i) { //比较版本大小 | ||
if (val1[i] > val2[i]) return 1; | ||
else if (val1[i] < val2[i]) return -1; | ||
} | ||
if (i < top1) { //由于可能有的版本还没遍历完 | ||
while (i < top1) if (val1[i++]) return 1; //只要版本后面的数字出现的不是0,就意味着两个版本不一样 | ||
}else{ | ||
while (i < top2) if (val2[i++]) return -1; | ||
} | ||
return 0; | ||
} | ||
//作者:ljj666 | ||
//链接:https://leetcode-cn.com/problems/compare-version-numbers/solution/cyu-yan-jian-jian-dan-dan-de-ji-xing-dai-ma-jie-37/ | ||
//来源:力扣(LeetCode) | ||
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 | ||
``` | ||
|
||
|
||
## 优秀解答 | ||
|
||
>暂缺 |