169. 多数元素
class Solution {
public int majorityElement(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums){
map.put(num, map.getOrDefault(num, 0)+1);
if (map.get(num) > nums.length/2) {
return num;
}
}
return 0;
}
}
没什么好说的,不过这种方式的空间复杂度是n
,使用了额外的数据结构
因为该数超过一半还多,也就是,如果把数组排序后,中间一定是这个数
例如:
例1:**1 1 1 1 2 ** 例2:**1 1 1 1 2 2 ** 例3:1 1 1 1 2 2 2 例3:1 1 1 1 2 2 2 2 (这就不是了)
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}
这样空间复杂度就是1
了
136. 只出现一次的数字
这道题通过上一题的想法,那么也可以使用先排序再查找的方法
class Solution {
public int singleNumber(int[] nums) {
Arrays.sort(nums);
for(int i=0; i< nums.length; i++){
if(i != nums.length-1 && nums[i] != nums[i+1] ){
return nums[i];
}else {
i++;
}
}
return nums[nums.length - 1];
}
}
位运算有个叫做:异或(^),位数相同就是0,位数不同就是1
以下是一个使用^=运算符的例子:
int a = 5; // 二进制表示为 00000101
int b = 3; // 二进制表示为 00000011
a ^= b; // a = a ^ b,即 a = 5 ^ 3
// 经过按位异或运算后,a的值发生变化,变为二进制表示的00000110,即十进制的6
System.out.println(a); // 输出6
那么把一个数,异或两次相同的数,会发生什么呐?
int a = 5; // 二进制表示为 00000101
int b = 3; // 二进制表示为 00000011
a ^= b; // a = a ^ b,即 a = 5 ^ 3, 则a = 00000110
a ^= b; // a = a ^ b,即 a = 6 ^ 3, 则00000110 与 00000011 进行异或运算
// 经过按位异或运算后,a的值发生变化,变为二进制表示的00000101,即十进制的5
System.out.println(a); // 输出5
会发现,最后等于原来的数,通过这种方式,回到题目
要找到不是两次的数,我只需要遍历一遍数组,然后每次都进行异或运算,最后得出来的结果,就是只出现一次的数
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for(int num : nums){
res ^= num;
}
return res;
}
}
75. 颜色分类
在第一次遍历中,我们从左向右遍历整个数组,如果找到了 0,那么就需要将 0 与「头部」位置的元素进行交换,并将「头部」向后扩充一个位置。在遍历结束之后,所有的 0都被交换到「头部」的范围,并且「头部」只包含 0。
在第二次遍历中,我们从「头部」开始,从左向右遍历整个数组,如果找到了 1,那么就需要将 1 与「头部」位置的元素进行交换,并将「头部」向后扩充一个位置。在遍历结束之后,所有的 1都被交换到「头部」的范围,并且都在 0 之后,此时 2 只出现在「头部」之外的位置,因此排序完成。
例如:nums = [2,0,2,1,1,0]
第一次遍历: 0,0,2,1,1,2
^
ptr
第二次遍历: 0,0,1,2,1,2
^
ptr
第二次遍历: 0,0,1,1,2,2
^
ptr
代码如下:
class Solution {
public void sortColors(int[] nums) {
int n = nums.length;
int ptr = 0;
for (int i = 0; i < n; ++i) {
if (nums[i] == 0) {
int temp = nums[i];
nums[i] = nums[ptr];
nums[ptr] = temp;
++ptr;
}
}
for (int i = ptr; i < n; ++i) {
if (nums[i] == 1) {
int temp = nums[i];
nums[i] = nums[ptr];
nums[ptr] = temp;
++ptr;
}
}
}
}
这里有两种双指针方案,我不偏向官方提供的答案
思路:
0 挪到最前面,2 挪到最后面
注意:2 挪完如果换出来的不是 1,那么指针要回退,因为 0 和 2 都是需要再次移动的
class Solution {
public void sortColors(int[] nums) {
int n = nums.length;
if (n < 2) {
return;
}
int p = 0, q = n - 1;
for (int i = 0; i <= q; ++i) {
if (nums[i] == 0) {
nums[i] = nums[p];
nums[p] = 0;
++p;
}
if (nums[i] == 2) {
nums[i] = nums[q];
nums[q] = 2;
--q;
// 注意回退
if (nums[i] != 1) {
--i;
}
}
}
return;
}
}
over~~~