落单的数(落单的数 & 落单的数 II & 落单的数 III)

来源:互联网 发布:南京弘历软件 编辑:程序博客网 时间:2024/05/22 03:21

落单的数

给出2*n + 1 个的数字,除其中一个数字之外其他每个数字均出现两次,找到这个数字。

样例
给出 [1,2,2,1,3,4,3],返回 4

挑战 
一次遍历,常数级的额外空间复杂度

思路1:利用异或的性质(自反性)

自反性:a ^ b ^ a = b.
异或运算最常见于多项式除法,不过它最重要的性质还是自反性:
A^B^ B=A,即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身。这是一个神奇
的性质,利用这个性质,可以获得许多有趣的应用。例如,所有的程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间:
设有A,B两个变量,存储的值分别为a,b,则以下三行表达式将互换他们的值 表达式(值):
A=A^B(a^b)
B=B^A(b^a^b=a)
A=A^B(a^b^a=b)


这道题利用了异或位运算的一个性质,即:一个数与自身异或的结果为0。我们只需遍历数组中的每一个元素,并将其进行异或。因为,异或满足交换律,所以最终的异或结果将仅仅包含只出现一次的那个数。
如:1 ^ 2 ^ 2 ^ 1 ^3 ^ 4 ^ 3 = 1 ^ 1 ^ 2 ^ 2 ^ 3 ^ 3 ^ 4 = 4

代码如下:

class Solution {public:    /*     * @param A: An integer array     * @return: An integer     */    int singleNumber(vector<int> A) {        // write your code here        //采用异或的操作可以解决这个问题        if(A.empty())return 0;        int n = A[0];        for(int i = 1;i != A.size();++i){            n = n^A[i];        }        return n;    }};
时间复杂度O(n),空间复杂度O(1)


思路二:

若一个数字出现2次,则该数字的二进制表示中每个位置的数值为1的出现次数为2次,如:5的二进制表示为101,若5出现3次,则其二进制表示中的第一个位置和第二个位置出现1的次数和均为2。那么对该位1出现的次数对2取余,最终的结果所对应的就是所要求的Sing Number。

代码:

class Solution {public:    /*     * @param A: An integer array     * @return: An integer     */    bool isBit1(int num, int index)  {        num = num >> index;        return (num & 1);    }    int singleNumber(vector<int> &A) {        int n = A.size();        int result = 0;        for(int i = 0; i < 32; ++i) {            int count = 0;            for(int j = 0; j < n; ++j) {                if(isBit1(A[j], i))                    ++count;            }            result |= (count % 2) << i;        }        return result;    }};
时间复杂度O(n),空间复杂度O(1)



落单的数 II

给出3*n + 1 个的数字,除其中一个数字之外其他每个数字均出现三次,找到这个数字。
样例
给出 [1,1,2,3,3,3,2,2,4,1] ,返回 4
挑战 
一次遍历,常数级的额外空间复杂度

思路:

与Single Number I 类似,所不同的是这道题除了一个数字之外都出现3次,仍然考虑使用位操作,尝试消除掉出现3次的数字。
若一个数字出现3次,则该数字的二进制表示中每个位置的数值为1的出现次数为3次,如:5的二进制表示为101,若5出现3次,则其二进制表示中的第一个位置和第二个位置出现1的次数和均为3。那么对该位1出现的次数对3取余,最终的结果所对应的就是所要求的Sing Number。
解题方法:与Single Number I 类似,所不同的是这道题除了一个数字之外都出现3次,仍然考虑使用位操作,尝试消除掉出现3次的数字。
若一个数字出现3次,则该数字的二进制表示中每个位置的数值为1的出现次数为3次,如:5的二进制表示为101,若5出现3次,则其二进制表示中的第一个位置和第二个位置出现1的次数和均为3。那么对该位1出现的次数对3取余,最终的结果所对应的就是所要求的Sing Number。
代码如下:

class Solution {public:/** * @param A : An integer array * @return : An integer  */    bool isBit1(int num, int index)  {        num = num >> index;        return (num & 1);    }    int singleNumberII(vector<int> &A) {        int n = A.size();        int result = 0;        for(int i = 0; i < 32; ++i) {            int count = 0;            for(int j = 0; j < n; ++j) {                if(isBit1(A[j], i))                    ++count;            }            result |= (count % 3) << i;        }        return result;    }};
时间复杂度O(n),空间复杂度O(1)


落单的数 III


给出2*n + 2个的数字,除其中两个数字之外其他每个数字均出现两次,找到这两个数字。
样例
给出 [1,2,2,3,4,4,5,3],返回 1和5
挑战 
O(n)时间复杂度,O(1)的额外空间复杂度


思路:

与以上两题不同的是,这道题有两个数只出现一次。基本的思路还是利用位运算,除去出现次数为2次的数。

如果对所有元素进行异或操作,最后剩余的结果是出现次数为1次的两个数的异或结果,此时无法直接得到这两个数具体的值。但是,因为这两个数一定是不同的,所以最终异或的值至少有一个位为1。我们可以找出异或结果中第一个值为1的位,然后根据该位的值是否为1,将数组中的每一个数,分成两个部分。这样每个部分,就可以采用Sing number I中的方法得到只出现一次的数。

代码:

class Solution {public:    /*     * @param A: An integer array     * @return: An integer array     */    int findindex(int number){        int index = 0;        while((number&1) == 0){            ++ index;            number >>= 1;        }        return index;    }            bool isBit1(int num, int index){        num = num >> index;        return (num & 1);    }        vector<int> singleNumberIII(vector<int> A) {        // write your code here        // if(A.empty())return vector<int>();        vector<int> result;        int twonumbers = 0;        for(int i =0;i!=A.size();++i){            twonumbers ^= A[i];        }        int index = findindex(twonumbers);        int num1 = 0,num2 = 0;        for(int i = 0;i!=A.size();++i){            if(isBit1(A[i],index)){                num1 ^= A[i];            }            else{                num2 ^= A[i];            }        }        result.push_back(num1);        result.push_back(num2);        return result;    }};

时间复杂度O(n),空间复杂度O(1)











原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 新股东入股公司之前的亏损怎么办 目前公司账面亏损有人要入股怎么办 土地确权后没有土地的人怎么办 老板不发工资跑路了怎么办 别人登录了我的美团账号怎么办 月嫂家政公司快坚持不下去了怎么办 华硕飞马4a手机发热怎么办 超级必发指数手机页面没曲线怎么办 唐小僧理财暴雷了投资者该怎么办 教师资格证面试准考证号忘了怎么办 初中学校说处分不给毕业证怎么办? 自动档一键打火的车没电了怎么办 物流代收货款一直拿不到钱怎么办 丰巢快递柜收不到验证码怎么办 拼多多三级惩罚下架3天怎么办 在万达买的衣服穿一次烂了怎么办 内蒙古对于没有地的农民改怎么办 微信号码重新注册后回零钱怎么办 安卓系统文件苹果手机打不开怎么办 课题必须发表论文吗?查重怎么办 学信网学籍绑定输错5次怎么办 大学学校图书馆借的书丢了怎么办 借阅机里的图书不显示书名怎么办 苹果6s锁屏密码忘了怎么办 父亲去世后妈将父亲存款带走怎么办 狗和别的狗打架腿瘸了怎么办 神经病砍人警察不积极处理怎么办 才买了车里面的气味很大怎么办 家里装修两年了很大的木味怎么办 装修一年的房子夏天味很大怎么办 死了怕下地狱活着又受煎熬怎么办 狗狗的疫苗证丢了怎么办 剃了毛的狗不睡觉怎么办 家里的小狗送人了孩子一直哭怎么办 半个月的小狗一天没拉屎怎么办 把狗狗的毛剃了怎么办 用了维a酸乳膏过敏怎么办 药水点痣留下的红印怎么办 小孩牙齿被虫子吃了个洞怎么办 一岁宝宝贫血值是84怎么办 荒岛求生手机版被困在石室里怎么办