您的位置:首页 > 其它

leetcode136:single number I&II 及拓展

2015-04-24 10:31 246 查看

Single Number I

给定一个数组,除了一个元素出现一次之外,其余的元素都出现次。找出这个元素

分析:

只要将所有的元素都异或一次,最后的结果就是这个出现一次数。

代码:

int singleNumber(int A[], int n) {
int num;
int i;
num=A[0];
for(i=1;i<n;i++)
{
num=num^A[i];
}
return num;
}


Single Number II

给定一个数组,除了一个元素出现一次之外,其余的元素都出现次。找出这个元素

分析:

考虑全部用二进制表示,将sizeof(int)大小的数组,每一位记录所有数字对应为1的个数。然后我们把 第ith个位置上所有数字的和对3取余,那么只会有两个结果 0 或 1 (根据题意,3个0或3个1相加余数都为0). 因此取余的结果就是那个出现一次的数。详细可以参考一下这篇博文

代码:

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


拓展一

一个数组,其中除两个数外,其余的都是成对出现的,找出这两个数

分析:

把数组中的所有元素异或,得到的结果为那两个不成对出现的数的异或值。然后在异或结果中找到第一个为1的位的位置,记为第N位。现在以第N位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N位都为1,而第二个子数组的每个数字的第N位都为0。

现在我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。

详细分析请见:链接 代码复制过来贴在下面了。

代码:

///////////////////////////////////////////////////////////////////////
// Find two numbers which only appear once in an array
// Input: data - an array contains two number appearing exactly once,
//               while others appearing exactly twice
//        length - the length of data
// Output: num1 - the first number appearing once in data
//         num2 - the second number appearing once in data
///////////////////////////////////////////////////////////////////////
void FindNumsAppearOnce(int data[], int length, int &num1, int &num2)
{
if (length < 2)
return;

// get num1 ^ num2
int resultExclusiveOR = 0;
for (int i = 0; i < length; ++ i)
resultExclusiveOR ^= data[i];

// get index of the first bit, which is 1 in resultExclusiveOR
unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);

num1 = num2 = 0;
for (int j = 0; j < length; ++ j)
{
// divide the numbers in data into two groups,
// the indexOf1 bit of numbers in the first group is 1,
// while in the second group is 0
if(IsBit1(data[j], indexOf1))
num1 ^= data[j];
else
num2 ^= data[j];
}
}

///////////////////////////////////////////////////////////////////////
// Find the index of first bit which is 1 in num (assuming not 0)
///////////////////////////////////////////////////////////////////////
unsigned int FindFirstBitIs1(int num)
{
int indexBit = 0;
while (((num & 1) == 0) && (indexBit < 32))
{
num = num >> 1;
++ indexBit;
}

return indexBit;
}

///////////////////////////////////////////////////////////////////////
// Is the indexBit bit of num 1?
///////////////////////////////////////////////////////////////////////
bool IsBit1(int num, unsigned int indexBit)
{
num = num >> indexBit;

return (num & 1);
}


拓展 二

1-100当中缺了两个数,求出这两个数

分析:

简单的数学方法是:计算a+b和a∗b的值,解方程求解

这里考虑转化为拓展一的方法。数组array[100],其下标正好为0-99,能不能利用上数组下标求解呢?答案是肯定的。这里将数组下标加一,变为1-100。将题目转化为array[0]…array[99]以及1-100 这总共200个数中,两个只出现一次的数。实现代码如下:

代码:

void find_lost_two(int array[],int length,int* num1,int* num2)
{
*num1 = 0;
*num2 = 0;
int temp = 0,i;
/* 计算200个数的异或和 */
for(i=0;i<100;i++)
{
temp ^=(i+1);
temp ^=array[i];
}

int first_not_zero=1;
/*找出异或和的最低1的位数*/
while(temp%2 == 0)
{
first_not_zero++;
temp = temp>>1;
}
/*按1进行划分*/
for(i=0;i<100;i++)
{
if(((1<<(first_not_zero-1))&(i+1)) == 0)

*num1 ^=(i+1);
else
*num2 ^=(i+1);
if(((1<<(first_not_zero-1))&array[i]) == 0)
*num1 ^=array[i];
else
*num2 ^=array[i];
}
}


参考资料:

1、http://zhedahht.blog.163.com/blog/static/2541117420071128950682/

2、http://blog.csdn.net/baidu20008/article/details/22095149
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: