Fork me on GitHub

137. Single Number II

欢迎fork and star:Nowcoder-Repository-github

137. Single Number II

题目

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

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

解析

  • 由于除去目标元素target之外,所有元素都出现3次,假设出现3次的元素有n个,这样的话假如我们统计所有元素的某一位(比如最后一位),其一共有3n+1个二进制位。因为对与同一个元素来说,其所有的二进制位一定是相同的,所以对这些元素的某一位来说一定是以3个1或3个0为单位出现的,即3n+1个二进制位中一定是3x个1和3y个0,其中x+y=n,再外加一个target对应的二进制位(1或0都有可能)。综上所述,我们可以统计所有数字每一位上1的个数,对3取模,如果为1就说明target对应位为1,否则为0。

  • 下面问题就是如何统计每一位上1的个数,一个比较好的方法就是采用位运算来处理,

//single number ii
class Solution_137 {
public:

	int singleNumber(int A[], int n) {
		int ret = 0;
		for (int i = 0; i < 32;i++)
		{
			int cnt = 0;
			for (int j = 0; j < n;j++)
			{
				cnt += (A[j] >> i) & 1;
			}
			ret += ((cnt % 3) << i);
		}
		return ret;
	}

	int singleNumber(vector<int>& nums) {
		//对每一位进行累加,对次数取模运算
		/* 把所有整数按照32位二进制进行每一位上的与1运算  结果为3n或3n+1;为3n+1的那些位就是只出现一次的数的二进制中1所在的位
		*/
		int ret = 0;
		for (int i = 0; i < 32; i++)
		{
			int cnt = 0;//计每一位的1的个数
			for (int j = 0; j < nums.size();j++)
			{
				cnt += (nums[i] >> i) & 1; //0的不需要考虑
			}
			//把3n+1的那些位的1移回原位并累加起来 |=  也行  
			ret += (cnt % 3) << i;
		}
		return ret;
	}
};

题目来源

posted @ 2017-12-26 11:44  ranjiewen  阅读(311)  评论(0编辑  收藏  举报