数组中出现次数超过一半的数字
思路分析:
方法一:先把数组进行排序,在有序数组中次数超过一半一定是中位数
(该方法的时间复杂度取决于排序算法的时间复杂度)
方法二:通过HashMap中的key记录元素的值,value为元素的次数
最后再遍历Hash,找到出现次数超过一半的数字
代码实现:
public static int moreThanHalfNum(int[] array) {
if (array == null){
return 0;
}
Map<Integer,Integer> res = new HashMap<>();
for (int i =0;i< array.length;i++){
//这个方法返回指定键所映射的值;如果此映射不包含该键的映射,则返回defaultValue(这里是0)
res.put(array[i],res.getOrDefault(array[i],0)+1);
if (res.get(array[i]) > array.length/2){
return array[i];
}
}
return 0;
}
数组中只出现一次的数字
leetcode136
题目要求:给出一个数组,除了某个元素只出现一次以外,其余每个元素均出现两次,找出那个只出现一次的元素
思路分析:
方法一:可以利用Set集合不存重复值的特点
也可以利用其他元素出现两次的特点,当遍历过程中发现遍历到的元素在集合中已经存在,不再进行添加操作,而是将集合中的key一起删除,最后剩下的就只有出现一次的数字
方法二:利用位运算中的异或运算
异或运算的规则
由于数组中只有一个数字只出现一次,所以只要利用一个变量,通过n次异或最后剩下的就是只出现一次的数字
代码实现:
//添加到HashSet集合中去
public int singleNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int i =0;i<nums.length;i++){
if(! set.add(nums[i])){
set.remove(nums[i]);
}
}
return set.toArray(new Integer[set.size()])[0];
}
//异或运算
public int singleNumber(int[] nums) {
int flag = 0;
for(int i =0;i<nums.length;i++){
flag ^= nums[i];
}
return flag;
}
颜色分类问题
leetcode75
题目要求:给定一个包含红色、白色和蓝色(用0、1、2表示),对它们进行排序,使得相同颜色相邻并按照红色、白色、蓝色顺序排序
思路分析:
方法一:基于冒泡排序的双指针(简单)
总共三个数字,所以只需要两次遍历,在第一次遍历中将所有0交换到数组的前面
第二次遍历将所有1交换到2的前面
方法二(一次遍历):
方法一是通过slow指针的移动,使得第一次遍历让所有0在slow指针的左边
基于这个思路,我们可以尝试三个指针
left指针: 让left的左侧元素全是0
right指针:让right的右侧元素全是2
index指针用于遍历整个链表,当index == right时说明遍历完成
代码实现:
//三指针一次遍历
public void sortColors(int[] nums) {
int left = 0;
int right = nums.length-1;
int index= 0;
for(;index <= right;){
//如果是2 index指针先不移动(可能调转回来的仍是2)
if(nums[index] == 2){
int temp = nums[right];
nums[right--] = nums[index];
nums[index] = temp;
}
//如果是0的情况直接放最前面 index也要随着变化
else if(nums[index] == 0){
int temp = nums[left];
nums[left++] = nums[index];
nums[index++] = temp;
}
//指针指向1的情况,最终结果是index的左边全是1
else {
index++;
}
}
}