前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode笔记:260. Single Number III

LeetCode笔记:260. Single Number III

作者头像
Cloudox
发布2021-11-23 15:19:08
3090
发布2021-11-23 15:19:08
举报
文章被收录于专栏:月亮与二进制月亮与二进制

问题:

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. For example: Given nums = [1, 2, 1, 3, 2, 5], return [3, 5]. Note:

  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

大意:

给出一个数字数组 nums,其中只有两个元素只出现过一次,其余的都出现了两次。找到只出现了一次的两个元素。 例子: 给出 nums = [1, 2, 1, 3, 2, 5], 返回 [3, 5]. 注意:

  1. 结果的顺序不重要,所以上面的例子中 [5, 3] 也是对的。
  2. 你的算法应该为线性的时间复杂度。你能不能只用恒定的空间复杂度?

思路:

最简单的方法就是排序后,依次检查相邻两个数是否相等,当然遇到相等的就要跳一个数字再进行检查,遇到不相等的就记录下来是结果,注意如果单个的元素排序后在最末尾,要单独处理。

这个做法排序是需要时间和空间的,并不完全符合题目的要求。

代码(Java):

代码语言:javascript
复制
public class Solution {
    public int[] singleNumber(int[] nums) {
        Arrays.sort(nums);
        
        int[] result = new int[2];
        int index = 0;
        
        int i = 0;
        for (; i < nums.length-1; i++) {
            if (nums[i] != nums[i+1]) {
                result[index] = nums[i];
                index ++;
            }
            else i++;
        }
        if (i < nums.length) result[index] = nums[i];
        
        return result;
    }
}

他山之石:

代码语言:javascript
复制
public class Solution {
    public int[] singleNumber(int[] nums) {
        // Pass 1 : 
        // Get the XOR of the two numbers we need to find
        int diff = 0;
        for (int num : nums) {
            diff ^= num;
        }
        // Get its last set bit
        diff &= -diff;
        
        // Pass 2 :
        int[] rets = {0, 0}; // this array stores the two numbers we will return
        for (int num : nums)
        {
            if ((num & diff) == 0) // the bit is not set
            {
                rets[0] ^= num;
            }
            else // the bit is set
            {
                rets[1] ^= num;
            }
        }
        return rets;
    }
}

好的,这是一个完全符合题目要求的做法,用到了按位异或和与的操作,是什么意思呢?

首先我们要知道异或的操作是指两个数同一位上相等时结果为0,不等时结果为1。如果是两个相同的数字异或,结果自然为0,而0与一个数异或,结果也是那个数,按照我们数组的特性,遍历异或后的结果将会是两个唯一的元素的异或结果。

得到两个数的异或结果后,我们要知道,这个结果中为0的位上说明两个数字相同,为1的位上说明两个数字不同,对于这一位,将数组中所有数字和其相与,必然会得到为0和为1两个结果阵营,而我们要的两个数就在两个阵营之中,那怎么分别在两个阵营中找出两个数呢?还是上面用过的手法,遍历异或。因为相同的两个数一定会进入同一个阵营,异或后又变成0了,最后就会凸显出要找的两个数了。

上面我们说要将第一次异或后的结果中找出某一位为1的值,怎么找呢?办法很多,这里的做法是将其与自己的负数相与,就会得出一个唯一一位为1的数了。

合集:https://github.com/Cloudox/LeetCode-Record

查看作者首页

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/11/23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题:
  • 大意:
  • 思路:
  • 代码(Java):
  • 他山之石:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档