题目136思路分析:
确定非空数组,其次每个元素均出现两次,某个元素只出现一次,说明数组的长度肯定是奇数。要求线性时间复杂度,说明不能嵌套循环,找出出现一次的元素。
- 思路1:关于计数可以用HashMap,统计元素出现的次数,最后遍历HashMap找到次数为1的元素即可。需要经过两次循环。
- 思路2:通过对数组排序,两两比较,即看 nums[i] 和 nums[i+1] 是否相等,如果相等,则i +=2。排序后会出现两种情况:
- 一种是:这个一次元素出现在数组的最后一个。一般是两两配对后,剩下最后一个,即i+1会正好等于数组的length,那么就返回nums[i]就是我们想要的答案了。
- 另一种是:这个一次元素不在数组的最后一个。如果不在最后一个,那么nums[i] != nums[i+1],直接返回nums[i]即可。
- 思路3:通过做题169,知道摩尔投票法也可以用来处理相同元素匹配个数等问题。
- 摩尔投票法简介:每次从序列中选择两个不相同的数字进行抵消或者删掉,最后剩下一个数字或几个相同的数字。
- 看到最后的那句话吗?剩下一个数字,这个就是我们想要的答案。
- 思路4:官方推荐的思路,用位运算符,这个题用的运算符为异或^。的的确确也满足没有使用额外空间。
- 异或运算符^:
- 如果有相同的元素相异或,如a^a,则会为0
- 如果有不相同的元素进行异或,如a^ b,则不会变。如果是a^ b^ a,则会变成a^ a^b = b
- 0^任何元素等于它本身。
- 异或运算符^:
public int singleNumber(int[] nums) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int i= 0; i< nums.length; i++){
if(map.containsKey(nums[i])){
int count = map.get(nums[i]);
map.put(nums[i],++count);
}else{
map.put(nums[i],1);
}
}
//遍历map
for(Map.Entry<Integer,Integer> item : map.entrySet()){
if(item.getValue() == 1){
int num = item.getKey();
return num;
}
}
return 0;
}
public int singleNumber(int[] nums) {
Arrays.sort(nums);
int i = 0;
while(i <= nums.length - 1){
if(i+1 >= nums.length){
return nums[i];
}
if (nums[i] == nums[i + 1]){
i = i + 2;
}else{
return nums[i];
}
}
return 0;
}
public int singleNumber(int[] nums) {
int res = 0,cnt = 0;
Arrays.sort(nums);
for( int num : nums){
if(cnt == 0){
res = num;
cnt++;
}else{
//相同元素我们要--,因为我们要找最少元素
res = num ? cnt-- : cnt++;
}
}
return res;
}
public int singleNumber(int[] nums) {
int res = 0;
for(int num : nums){
res = res ^ num;
}
return res;
}
题目169思路分析:
要求找到数组中出现次数大于n/2的元素。
- 思路1:还是可以用HashMap,统计元素出现的次数,最后遍历HashMap找到次数大于n/2的元素即可。需要经过两次循环。
- 思路2:摩尔投票法,不过现在的情况,不是需要剩下一个数字了,而是多个数字,或者说多个相同的数字。所以代码会与136有点点不同。
- 思路3:看评论知道还有众数这个解法,果然还是评论区神仙多,因为数组中出现次数大于数组长度的一半,可以肯定需要找的数一定是众数,且经过排序,这个数一定会出现在数组长度一半的位置。
public int majorityElement(int[] nums) {
HashMap<Integer,Integer> map = new HashMap<>();
int n = nums.length;
for(int num : nums){
if(map.containsKey(num)){
int count = map.get(num);
map.put(num,++count);
}else{
map.put(num,1);
}
}
for(Map.Entry<Integer,Integer> item : map.entrySet()){
if(item.getValue() > n/2){
return item.getKey();
}
}
return 0;
}
public int majorityElement(int[] nums) {
int res = 0,cnt = 0;
for( int num : nums){
if(cnt == 0){
res = num;
cnt++;
}else{
//相同的元素,我们要++,因为我们要找多数元素
res = num ? cnt++ : cnt--;
}
}
return res;
}
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}