Skip to content

Commit 8d6654f

Browse files
committed
solve #137
1 parent 948f712 commit 8d6654f

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,4 @@ mod n0132_palindrome_partitioning_ii;
134134
mod n0134_gas_station;
135135
mod n0135_candy;
136136
mod n0136_single_number;
137+
mod n0137_single_number_ii;

src/n0137_single_number_ii.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* [137] Single Number II
3+
*
4+
* Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
5+
*
6+
* Note:
7+
*
8+
* Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
9+
*
10+
* Example 1:
11+
*
12+
*
13+
* Input: [2,2,3,2]
14+
* Output: 3
15+
*
16+
*
17+
* Example 2:
18+
*
19+
*
20+
* Input: [0,1,0,1,0,1,99]
21+
* Output: 99
22+
*
23+
*/
24+
pub struct Solution {}
25+
26+
// submission codes start here
27+
28+
/*
29+
糅合了一下 https://leetcode.com/problems/single-number-ii/discuss/43296/An-General-Way-to-Handle-All-this-sort-of-questions. 和 https://leetcode.com/problems/single-number-ii/discuss/43294/Challenge-me-thx
30+
31+
第一个链接给出了通用解法: 对于一个数出现 M 次其它数都出现了 K 的场景, 我们可以用位运算记录 K 种状态(作为一个计数器)来解
32+
33+
这题的真值表(3种状态使用2位):
34+
35+
a b c/c a'b'/a'b'
36+
0 0 1/0 0 1 /0 0
37+
0 1 1/0 1 0 /0 1
38+
1 0 1/0 0 0 /1 0
39+
40+
根据数电的知识, 要根据这个真值表写出逻辑表达式, 以输出端为 '1' 的结果为准, 将每行的输入变量写成 AND 形式, 其中为 0 的输入量需要取反, 再将这几个 AND 形式做 OR 即可
41+
42+
令 a' = 1, 则:
43+
44+
a b c a'
45+
0 1 1 1 ~a & b & c
46+
1 0 0 1 a & ~b & ~c
47+
48+
a' = (~a & b & c) | (a & ~b & ~c)
49+
50+
同理:
51+
52+
b' = (~a & b & ~c) | (~a & ~b & c)
53+
54+
这个每轮计算的位次数达到 17 次, 可以再优化一下:
55+
56+
对 b' 化简: b' = ~a & (b & ~c | ~b & c) = ~a & b ^ c
57+
58+
但这时 a 仍然比较复杂, 我们可以考虑能否用每轮算出的 b' 来简化 a 的计算, 则:
59+
60+
a (b) b' c a' b'
61+
1 (0) 0 0 1 0
62+
0 (1) 0 1 1 0
63+
64+
重写一下就是 a' = (a & ~b' & ~c) | (~a & ~b' & c) = ~b' & (a & ~c | ~a & c) = ~b' & a ^ c
65+
66+
这个就和最开始第二链接里给出的超简洁解法一致了
67+
68+
最后的话, a 或 b 为 1 都可以输出到 1 (目标数出现1次或出现2次), 输出 a | b 即可
69+
*/
70+
impl Solution {
71+
pub fn single_number(nums: Vec<i32>) -> i32 {
72+
let (mut a, mut b) = (0, 0);
73+
for &num in nums.iter() {
74+
b = !a & (b ^ num);
75+
a = !b & (a ^ num);
76+
}
77+
return a | b
78+
}
79+
}
80+
81+
// submission codes end
82+
83+
#[cfg(test)]
84+
mod tests {
85+
use super::*;
86+
87+
#[test]
88+
fn test_137() {
89+
assert_eq!(Solution::single_number(vec![0,0,0,1,1,1,5]), 5);
90+
}
91+
}

0 commit comments

Comments
 (0)