【力扣算法】136-只出现一次的数字

题目

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1

示例 2:

输入: [4,1,2,1,2]
输出: 4

题解

无官方题解

这道题目核心在于异或……评论区大佬还是厉害。自己一开始没注意到要求不使用额外空间的要求,只是去用HashSet搞了个线性时间复杂度就算了。

看了一个评论区大佬的题解:感觉除了异或的方法。解法二提到了排序的想法也是可以的:先排序,然后利用两两成对的时候,“索引为偶数时,和后一个配对相等,奇数时与前一个配对相等”的性质,可以进行二分查找。总的来说,排序复杂度O(nlogn),二分查找O(logn),最后复杂度O(nlogn)。虽然没达到题目要求的O(n),但是没有使用额外空间,还是可以的了。

附一下异或的做法:

执行用时 : 1 ms, 在Single Number的Java提交中击败了99.60% 的用户

内存消耗 : 40.6 MB, 在Single Number的Java提交中击败了68.37% 的用户

int ans = nums[0];
if (nums.length > 1) {
   for (int i = 1; i < nums.length; i++) {
      ans = ans ^ nums[i];
   }
 }
 return ans;

算法原理在于,对一个数进行两次同一个数的异或会恢复原来的数。

评论区大佬的题解里面还提到了HashMap的方法,HashMap存次数,跑起来比我的方法还慢一点点。。。应该是HashSet remove比HashMap去遍历get还快。。。但内存消耗比我少就很迷

执行用时 : 28 ms, 在Single Number的Java提交中击败了13.61% 的用户

内存消耗 : 41.5 MB, 在Single Number的Java提交中击败了38.97% 的用户

class Solution {
    public int singleNumber(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        for (Integer i : nums) {
            Integer count = map.get(i);
            count = count == null ? 1 : ++count;
            map.put(i, count);
        }
        for (Integer i : map.keySet()) {
            Integer count = map.get(i);
            if (count == 1) {
                return i;
            }
        }
        return -1; // can't find it.
    }
}

感想

自己用的HashSet:

执行用时 : 22 ms, 在Single Number的Java提交中击败了19.24% 的用户

内存消耗 : 44 MB, 在Single Number的Java提交中击败了9.02% 的用户

class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        HashSet<Integer> hs = new HashSet<>();
        for(int i:nums){
            if(hs.contains(i))hs.remove(i);
            else hs.add(i);
        }
        for(int i:hs){
            res = i;
        }
        return res;
    }
}

set只有一个元素剩下的时候怎么输出都不是很清楚,用了个很蠢的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值