Boostable

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

LeetCode: Single Number

Given an array of integers, every element appears twice except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

地址:https://oj.leetcode.com/problems/single-number/

算法:这题应该超简单吧,直接异或,代码:

 1 class Solution {
 2 public:
 3     int singleNumber(int A[], int n) {
 4         int result = 0;
 5         for(int i = 0; i != n; ++i){
 6             result ^= A[i];
 7         }
 8         return result;
 9     }
10 };

Given an array of integers, every element appears three times except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

地址:https://oj.leetcode.com/problems/single-number-ii/

算法:这道题我是用数字逻辑上的想法来做的。按照题目的要求,如果各个位连续三次出现1,则该位最后位运算的结果应该是0,现在我们设置两个变量a和b,其中a和b中对应位中的二进制信息用于统计这个位中1出现的次数。比如,若a,b的第一位为00,则表示第一位中1出现的次数为零次;若a,b的第一位为01,则表示第一位中1出现的次数为一次;若为10则表示1出现的次数为两次。这样,我们就可以根据当前的输入来改变a,b的状态来统计每一位中1出现的次数。具体的说,a,b状态位按如下方式转移:

ab 0 1
00 00 01
01 01 10
10 10 00

其中第一列表示ab所处的状态,第一行表示输入的状态。比如若ab状态为00,输入为1,则ab的状态转为01。有了上述ab状态的转移表,我们就可以利用数字逻辑写出转移后的状态和转移前状态的逻辑关系,具体公式如下:

\begin{align*}&a^\prime = (\bar{x}\&a) | (x\&a\&0)|(x\&\bar{a}\&b)\\ &b^\prime=(\bar{x}\&b)|(x\&\bar{a}\&\bar{b})|(x\&\bar{a}\& b)|(x\& a\&\bar{b})\end{align*}

其中$a^\prime,b^\prime$表示转移后的状态,$x$表示输入。上述公式化简后为:

\begin{align*}&a^\prime=(\bar{x}\&a)|(x\&\bar{a}\&b)\\ &b^\prime=(\bar{x}\&b)|(x\&\bar{a}\&\bar{b})\end{align*}

有了上述的公式,代码也就很简单了:

class Solution {
public:
    int singleNumber(int A[], int n) {
        int a = 0;
        int b = 0;
        int t_a = 0, t_b = 0;
        for(int i = 0; i != n; ++i){
            t_b = (~A[i] & b) | (A[i] & (~b) & (~a));
            t_a = (~A[i] & a) | (A[i] & (~a) & b);
            b = t_b;
            a = t_a;
        }
        return a | b;
    }
};

 

posted on 2014-08-23 11:56  Boostable  阅读(192)  评论(0编辑  收藏  举报