Skip to content

Commit f2b5f61

Browse files
committed
位操作: 只出现1次的数字(3)
Change-Id: I63bbc2821d659cdc86b7e82433edad0f2b21763c
1 parent b1629dd commit f2b5f61

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

go/leetcode/136.只出现一次的数字.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
*/
3434

3535
// @lc code=start
36+
// 异或:相同的位置置0,不同的位置1
37+
// 因此,对数组所有元素进行异或,出现2次的数字的所有位被抵消了,只剩出现1次的数字
3638
func singleNumber(nums []int) int {
3739
ret := nums[0]
3840
for i := 1; i < len(nums); i++ {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* @lc app=leetcode.cn id=137 lang=golang
3+
*
4+
* [137] 只出现一次的数字 II
5+
*
6+
* https://leetcode-cn.com/problems/single-number-ii/description/
7+
*
8+
* algorithms
9+
* Medium (64.83%)
10+
* Likes: 210
11+
* Dislikes: 0
12+
* Total Accepted: 15.8K
13+
* Total Submissions: 24.4K
14+
* Testcase Example: '[2,2,3,2]'
15+
*
16+
* 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
17+
*
18+
* 说明:
19+
*
20+
* 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
21+
*
22+
* 示例 1:
23+
*
24+
* 输入: [2,2,3,2]
25+
* 输出: 3
26+
*
27+
*
28+
* 示例 2:
29+
*
30+
* 输入: [0,1,0,1,0,1,99]
31+
* 输出: 99
32+
*
33+
*/
34+
35+
// @lc code=start
36+
func singleNumber(nums []int) int {
37+
ret := 0
38+
// 遍历32个位,分别统计每个位上1的个数,除掉特殊的那个数字,其他数字都出现了3次,所以个数必然是3的倍数
39+
// 只要将个数模3,就可以得到特殊数在这个位上是否为1了
40+
for i := 0; i < 64; i++ { // 注意64位机器上int就是64位,如果写的32则在64位机器会失败
41+
sum := 0
42+
for _, num := range nums {
43+
sum += (num >> i) & 1 // 第i位是否为1
44+
}
45+
ret |= (sum % 3) << i // sum%3是目标数在该位的值
46+
}
47+
return ret
48+
}
49+
// @lc code=end
50+

go/leetcode/260.只出现一次的数字-iii.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
*/
3131

3232
// @lc code=start
33+
// 先将数组整体异或得到两个不同数字的异或结果,因为这两个数字不同,所以异或结果必然不为0
34+
// 异或结果中1的位就是两者不同的位,也就是某个数为1的位,找一个这样的位然后将其他位置为0,得到一个flag
35+
// 遍历数组,用这个flag去与,如果不为0则表示这个位是1,为0则表示这个位是0,这样就将不同的两个数分在两个组里面了
36+
// 对这两个组分别组内异或,就能得到两个不同的数字
3337
func singleNumber(nums []int) []int {
3438
diff := nums[0]
3539
for i := 1; i < len(nums); i++ {

0 commit comments

Comments
 (0)