数组中出现次数超过一半的数字
使用Hash
我们先创建一个HashMap的key是元素的值,value是已经出现的次数,然后遍历数组来统计所有元素出现的次数。最后再次遍历Hash,找到出现次数超过一半的数字
public int moreThanHalfNum(int [] array) {
if(array==null)
return 0;
Map<Integer,Integer> res=new HashMap<>();
int len = array.length;
for(int i=0;i<array.length;i++){
res.put(array[i],res.getOrDefault(array[i],0)+1);
if(res.get(array[i])>len/2)
return array[i];
}
return 0;
}
数组中出现一次的数字
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
Set集合
public static Integer findOneNum(int[] arr) {
Set<Integer> set = new HashSet<Integer>();
for(int i : arr) {
if(!set.add(i))//添加不成功返回false,前加上!运算符变为true
set.remove(i);//移除集合中与这个要添加的数重复的元素
}
//注意边界条件的处理
if(set.size() == 0)
return null;
//如果Set集合长度为0,返回null表示没找到
return set.toArray(new Integer[set.size()])[0];
}
位运算
class Solution {
public int singleNumber(int[] nums) {
int flag = 0;
for(int i : nums) {
flag ^= i;
}
return flag;
}
}
颜色分类问题
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
基于冒泡排序的双指针
我们可以考虑对数组进行两次遍历。在第一次遍历,我们将数组中所有的 0 交换到数组的头部,这样第二次遍历只需要处理1和2的问题就行了,而这两次寻找本身又是非常漂亮的双指针。代码如下:
class Solution {
public void sortColors(int[] nums) {
int n = nums.length;
int left = 0;
//将所有的0交换到数组的最前面
for (int right = 0; right < n; right++) {
if (nums[right] == 0) {
int temp = nums[right];
nums[right] = nums[left];
nums[left] = temp;
left++;
}
}
//将所有的1交换到2的前面
for (int right = left; right < n; ++right) {
if (nums[right] == 1) {
int temp = nums[right];
nums[right] = nums[left];
nums[left] = temp;
++left;
}
}
}
}
三指针
如果要求只用一次遍历就要解决问题,该怎么办呢?我们隐约感觉到要使用三个指针才行:
- left指针,表示left左侧的元素都是0
- right指针 ,表示right右侧的元素都是2
- index指针,从头到尾遍历数组,根据nums[index]是0还是2决定与left交换还是与right交换。
index位置上的数字代表着我们当前需要处理的数字。当index为数字1的时候,我们什么都不需要做,直接+1即可。如果是0,我们放到左边,如果是2,放到右边。如果index=right,则可以停止。 我们看一下图示:
这里的重点和难点index位置为2进行交换后为什么只进行right--,而不用index++呢?这是因为我们right位置交换过来的元素可能是0,也可能是1。如果是0自然没问题,但是如果是1则执行index++就将1跳过了无法处理了。所以我们先不动index,在下一次循环时继续判断这个index位置元素是不是0。
那为啥index位置是0的时候执行swap就可以index++了呢,这是因为如果index前面位置如果存在位置都会被swap到right位置去了,这里只需要处理0和1的情况就可以了。
代码如下:
public void sortColors(int[] nums) {
int left=0,right=nums.length-1;
int index=0;
while(index<=right){
if(nums[index]==0)
swap(nums,index++,left++);
else if(nums[index]==2)
swap(nums,index,right--);
else
index++;
}
}
private void swap(int[] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}