【LeetCode】136.只出现一次的数字 && 169.多数元素

请添加图片描述

题目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];
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值