第三关数组(黄金)
1 数组中出现次数超过一半的数字
/**
* 方法1 基于Hash
* @param array
* @return
*/
public static 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;
}
public static int majorityElement(int[] nums) {
int count = 0;
Integer candidate = null;
//如果存在中位数,那么中位数的数量一定比其他的数量大
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
2 数组中只出现一次的数字
/**
* 基于集合寻找
* @param arr
* @return
*/
public static Integer findOneNumTwo(int[] arr) {
Set<Integer> hashSet=new HashSet<>();
for (int i : arr) {
if (!hashSet.add(i)){
hashSet.remove(i);
}
}
if (hashSet.size()==0){
return null;
}
//如果Set集合长度为0,返回null表示没找到
return hashSet.toArray(new Integer[hashSet.size()])[0];
}
/**
* 基于位运算
* @param arr
* @return
*/
public static int findOneNum2(int[] arr) {
int flag = 0;
for(int i : arr) {
flag ^= i;
}
return flag;
}
3 颜色分类问题(荷兰国旗问题)
public static 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;
}
}
}
public static void sortColorsTwo(int[] nums) {
int left=0,right=nums.length-1;
int index=0;
while(index<=right){
if (nums[index]==0){
//是0的时候交换后index往后移动
swap(nums,index++,left++);
}else if (nums[index]==2){
//是2的时候交换后index不移动
swap(nums,index,right--);
}else {
index++;
}
}
}
private static void swap(int[] nums,int i,int j){
int tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}