我的算法10

该文章包含三题,为同一类题目。难道依次增加。

第一题:

题目地址https://leetcode.com/problems/single-number/#/description
题目描述:Given an array of integers, every element appears twice except for one. Find that single one.

我的代码

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int a=0;
        for(int i=0;i<nums.size();i++)
            a^=nums[i];
            return a;
    }
};

解题思路
0^a=a;
a^a=0;
且a1^a2^a3^……^an的结果与顺序无关。
所以,设nums里面有2个a1,a2,……ak,和一个b0.
则a=0^nums0^nums1……^numn-1=0^b0^a1^a1……^ak^ak=b0.

第二题:

题目地址https://leetcode.com/problems/single-number-ii/#/description
题目描述
Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
我的代码

//方法一:
class Solution {
public:
       int singleNumber(vector<int>& s) 
    {
        vector<int> t(32);Made a array contain 32 elements.
        int sz = s.size();
        int i, j, n;
        for (i = 0; i < sz; ++i)
        {
            n = s[i];
            for (j = 31; j >= 0; --j)
            {
                t[j] += n & 1;//Find the last digit.
                n >>= 1;
                if (!n)
                    break;
            }
        }
    int res = 0;
    for (j = 31; j >= 0; --j)
    {
        n = t[j] % 3;//"3" represents k times. 
        if (n)
            res += 1 << (31 - j);
    }
    return res;
}
};

//方法二:
class Solution {
public:
       int singleNumber(vector<int>& s) 
    {
        int one=0,two=0;
        for(int i=0;i<s.size();i++){
            one=(one^s[i])&~two;
            two=(two^s[i])&~one;
        }
        return one;
    }
};

解题思路
首先来看方法一,
方法一是将所有的数化为二进制数,由于int最多只有32位。所有用一个数组分别将s中所有元素的二进制第k位的值加起来。即记录有多少个数的第k位为1.
由于除了一个元素是不重复的以外,其他元素都是三重复的。所以讲记录的值模3后,所表示的就是剩下的不重复的元素在第k位是0还是1.如此,通过移位相加便可得到这个元素。
再看方法二。
方法二依然是按二进制位处理,不过并非记录,而是直接用逻辑运算。简单证明便可知其有三个性质:
(1)对one=0,two=0,对a做一步运算,结果one=a;
(2)对one=0,two=0,对a连续做三次运算,结果one=0,two=0.
(3)对任意one,及相应two,对a,b运算的顺序不影响结果。
如此显然,结果成立。
法一和法二复杂度相同,虽然法二代码更为简洁,但对由改三条性质构造关系式却相当复杂,而法一逻辑简单,扩展性更好。

第三题

题目地址https://leetcode.com/problems/single-number-iii/#/description
题目描述: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.

我的代码

class Solution { 
public: vector<int> singleNumber(vector<int>& nums) { 
    int r = 0, n = nums.size(), i = 0, last = 0; 
    vector<int> ret(2, 0); 
    for (i = 0; i < n; ++i)  r ^= nums[i]; 
    last = r & (~(r - 1)); 
    for (i = 0; i < n; ++i) { 
        if ((last & nums[i]) != 0) 
        ret[0] ^= nums[i]; 
        else ret[1] ^= nums[i];       
    } 
    return ret;  
} 
};

解题思路
如第一题,先异或消去所有二重复元素,得到b0^b1的值r,然后用异或值来求出b0,b1的一个不同的二进制位,last在该为为1,其他所有位为0,然后通过&将unms中的数分成两类,即该位为1还是为0.然后依然通过异或消去重复即可得结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值