Ykuri98
文章46
标签14
分类1
剑指offer-day22

剑指offer-day22

数组中数字出现的次数Ⅰ

说实话,位运算方面的算法真的很难想,基本都要靠别人的思路,代码虽然简洁但是很难看懂。

这道题目非常像只出现一次的数字,但是只出现一次的数字变成了两个,这说明原来遍历并异或的思路行不通了,但是这个思路是个出发点。在遍历并异或后,就可以获得两个不同的数异或的值,由于异或的特性(一者为0一者为1,结果为1,否则为0),可以确定在结果的二进制中,最低位的1所在的位,在两个数中分别是1和0,那么可以根据这个线索将数组分成两个,一个在该位全是1,另一个则全是0,而且相同的数,它们在该位的数一定相同,那么这两个数组中就是数对相同的数和一个不同的数,对这两个数组进行异或运算,得出来的就是结果了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public int[] singleNumbers(int[] nums) {
int sum = 0;

// 获得整个数组异或后的值
for(int i : nums){
sum ^= i;
}
int n = 1;

// 结果跟1进行与运算,等于0说明结果的倒数第一位是0,n左移一位让1从最低位移到倒数第二位,重复至找到第一个和结果进行与运算的值为1的n,此时n就是结果里最低位为1,其他位为0的值。
while((sum & n) == 0){
n <<= 1;
}
int x = 0;
int y = 0;
// 根据n来对数组里每个数进行与运算,数的二进制在该位为0和在该位为1的值分成两组,对这两组分别进行异或运算
for(int i : nums){
if((i & n) != 0){
x ^= i;
}
else{
y ^= i;
}
}
int[] res = {x,y};
return res;
}
}

数组中数字出现的次数Ⅱ

这道题目的最优解引入了一个算法,叫有限状态转换机,但是我看不懂这个算法,只能作罢,直接背代码算了。

1
2
3
4
5
6
7
8
9
10
11
12
// 看不懂
class Solution {
public int singleNumber(int[] nums) {
int one = 0;
int two = 0;
for(int i : nums){
one = one ^ i & ~two;
two = two ^ i & ~one;
}
return one;
}
}

其实题目并没有限制o(n)时间和o(1)空间,完全是可以用hashmap做的。

本文作者:Ykuri98
本文链接:https://ykuri98.github.io/2022/04/28/%E5%89%91%E6%8C%87offer-day22/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×