1.数字出现的次数超过数组长度的一半
方法一、使用Map键值对来记录每个元素出现的次数,返回次数大于一半的
class Solution {
public int majorityElement(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++){
map.put(nums[i],map.getOrDefault(nums[i],0)+1);
if(map.get(nums[i])>nums.length/2){
return nums[i];
}
}
return 0;
}
}
方法二、投票算法,我愿称之为自相残杀一换一算法
关键是把握同时减少一个众数和非众数并不会影响众数的地位
例如: [1, 2, 3, 2, 2, 2, 5, 4, 2]
令result = 1 times = 1
当下一个不与result相等时就减一,否则就加一(敌方一换一,我方纳入阵营)
当减为零的时候就更换result为下一个值(自相残杀全g)
开始循环1,2不相同,times-1为0,result更换为3,剩余 [ 3, 2, 2, 2, 5, 4, 2]
3,2不相同,times-1为0,result更换为2,剩余[ 2, 2, 5, 4, 2]
2,2相同,times+1为2,剩余[ 5, 4, 2]
2,5不相同,times-1为1,剩余[ 4 , 2 ]
2,4不相同,times-1为0,更换为2
最终2胜出
class Solution {
public int majorityElement(int[] nums) {
int result = 0;
int times = 0;
for(int i = 0;i<nums.length;i++){
if(times == 0){
result = nums[i];
}
times = (nums[i] == result) ? times+1 : times-1;
}
return result;
}
}
2. 只出现一次的数字
方法一、使用辅助哈希表
这里使用Set集合去重特性比使用Map集合更优,不需要再一次遍历Map
class Solution {
public int singleNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int num : nums){
if(!set.add(num)){
set.remove(num);
}
}
return set.toArray(new Integer[0])[0];
}
}
方法二、位运算之异或
关键把握相同数字异或结果为0,因为异或位运算的本质就是每位相同取0不同取1,数字相同结果就是全部取0。
当数组中仅一个数字是单独的,其他都是两两成对,就说明异或运算下来最终结果就是单独的那个数字,其他全部取0。
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for(int num : nums){
res ^= num;
}
return res;
}
}
3.颜色分类(荷兰国旗)
方法一、单指针
循环一遍将0交换到前面
再循环一遍将1交换到中间
class Solution {
public void sortColors(int[] nums) {
int n = nums.length;
int p = 0;
for(int i = 0;i<nums.length;i++){
if(nums[i] == 0){
int t = nums[p];
nums[p] = nums[i];
nums[i] = t;
p++;
}
}
for(int i = p;i<nums.length;i++){
if(nums[i] == 1){
int t = nums[p];
nums[p] = nums[i];
nums[i] = t;
p++;
}
}
}
}
方法二、双指针
p0保留交换0的位置
p1保留交换1的位置
遍历一遍:当值为0直接和p0交换,一个元素成功归位,一个萝卜一个坑,p0++、p1++,
当值为1和p1交换,元素并不代表成功归位(1得在0后面),但还是一个萝卜一个坑, p0不能动,p1++
但是注意会出现这么一种状况,当元素为1时和p1交换但是p0没动,p1>p0,下一次遇到0和p0交换就会把1换到后面去,需要和p1再交换一次,这时才算归位
class Solution {
public void sortColors(int[] nums) {
int p0 = 0;
int p1 = 0;
for(int i = 0;i<nums.length;i++){
if(nums[i] == 0){
swap(nums,p0,i);
if(p0<p1){
swap(nums,p1,i);
}
p1++;
p0++;
}else if(nums[i] == 1){
swap(nums,p1,i);
p1++;
}
}
}
public void swap(int[] nums,int n,int m){
int t = nums[n];
nums[n] = nums[m];
nums[m] = t;
}
}