数组中只出现一次的数字(剑指offer)思维有点巧
2015-10-01 18:59
351 查看
数组中只出现一次的数字
参与人数:1144时间限制:1秒空间限制:32768K
通过比例:21.75%
最佳记录:0 ms|0K(来自 牛客563536号)
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
题目链接:http://www.nowcoder.com/practice/e02fdb54d7524710a7d664d082bb7811?rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
首先题目里有个很关键的信息:除了两个数字之外,其他的数字都出现了两次。作为这题的突破口!
那么先来想想这样的情况,一个数组中,除了一个数,其他数都出现偶数次的情况!
看这题目的信息,就是透露你要用异或来求解的嘛,(偶数次异或为0),所以我们只要把整个数组都异或一次就可以解决问题了。
那么现在来想2个数的情况,有人说也都异或一遍不就好了。可是这样就得到了我们要求的那两个数的异或后的结果了,而不能得到要求的那2个数,所以还差一点点;
考虑这样一个数组:1 1 2 3 3
4 4 5 6 6 发现如果要求2个数分别位于2个数组中,那么2个数组分别异或就能得到解不是吗?! 就好好像两个问题一组合成问题二一样,(思想没错!)
我们知道现在最主要的问题是把原数组拆成2个问题一的数组。(eg:1 2 3 4 5 1 2 3)
这里有个小技巧:因为相同数字异或为0,不同数字异或不为0,所以结果一定不是0;设异或结果为ans,那么我们可以找到ans的二进制某一位一定为1,so。。这一位一定来自num1或者num2;所以以这一位为分界条件,把数组分成2部分,eg:ans=1;数组分成{1,3,5,3,1}和{2,4,2}
这样每个数组再异或就可以得到解了!
#include<stdio.h>
#include<vector>
using namespace std;
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int *num1,int *num2) {
if(data.size()<2) return ;
int ans=data[0];
int len=data.size();
for(int i=1;i<len;i++)
{
ans^=data[i];
}
if(ans==0) return ;//没有两个不一样的
int f=1;
for(int i=1;;i++)
{
if(f&ans) break;
f=1<<i;
}
// printf("%d\n",f);
*num1=0;
*num2=0;
for(int i=0;i<len;i++)
{
if(f&data[i])
{
*num1^=data[i];
}
else
{
*num2^=data[i];
}
}
}
};
int main()
{
vector<int> arr(10);
arr[0]=1;
arr[1]=2;
arr[2]=3;
arr[3]=4;
arr[4]=5;
arr[5]=1;
arr[6]=2;
arr[7]=3;
arr[8]=7;
arr[9]=7;
Solution so;
int a;
int b;
int *num1=&a;
int *num2=&b;
so.FindNumsAppearOnce(arr,num1,num2);
printf("%d\t%d\n",*num1,*num2);
return 0;
}
参与人数:1144时间限制:1秒空间限制:32768K
通过比例:21.75%
最佳记录:0 ms|0K(来自 牛客563536号)
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。题目链接:http://www.nowcoder.com/practice/e02fdb54d7524710a7d664d082bb7811?rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
首先题目里有个很关键的信息:除了两个数字之外,其他的数字都出现了两次。作为这题的突破口!
那么先来想想这样的情况,一个数组中,除了一个数,其他数都出现偶数次的情况!
看这题目的信息,就是透露你要用异或来求解的嘛,(偶数次异或为0),所以我们只要把整个数组都异或一次就可以解决问题了。
那么现在来想2个数的情况,有人说也都异或一遍不就好了。可是这样就得到了我们要求的那两个数的异或后的结果了,而不能得到要求的那2个数,所以还差一点点;
考虑这样一个数组:1 1 2 3 3
4 4 5 6 6 发现如果要求2个数分别位于2个数组中,那么2个数组分别异或就能得到解不是吗?! 就好好像两个问题一组合成问题二一样,(思想没错!)
我们知道现在最主要的问题是把原数组拆成2个问题一的数组。(eg:1 2 3 4 5 1 2 3)
这里有个小技巧:因为相同数字异或为0,不同数字异或不为0,所以结果一定不是0;设异或结果为ans,那么我们可以找到ans的二进制某一位一定为1,so。。这一位一定来自num1或者num2;所以以这一位为分界条件,把数组分成2部分,eg:ans=1;数组分成{1,3,5,3,1}和{2,4,2}
这样每个数组再异或就可以得到解了!
#include<stdio.h>
#include<vector>
using namespace std;
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int *num1,int *num2) {
if(data.size()<2) return ;
int ans=data[0];
int len=data.size();
for(int i=1;i<len;i++)
{
ans^=data[i];
}
if(ans==0) return ;//没有两个不一样的
int f=1;
for(int i=1;;i++)
{
if(f&ans) break;
f=1<<i;
}
// printf("%d\n",f);
*num1=0;
*num2=0;
for(int i=0;i<len;i++)
{
if(f&data[i])
{
*num1^=data[i];
}
else
{
*num2^=data[i];
}
}
}
};
int main()
{
vector<int> arr(10);
arr[0]=1;
arr[1]=2;
arr[2]=3;
arr[3]=4;
arr[4]=5;
arr[5]=1;
arr[6]=2;
arr[7]=3;
arr[8]=7;
arr[9]=7;
Solution so;
int a;
int b;
int *num1=&a;
int *num2=&b;
so.FindNumsAppearOnce(arr,num1,num2);
printf("%d\t%d\n",*num1,*num2);
return 0;
}
相关文章推荐
- ruby 数组使用教程
- Ruby中的数组和散列表的使用详解
- C#实现AddRange为数组添加多个元素的方法
- C#动态调整数组大小的方法
- 详解Lua中的数组概念知识
- Perl中的列表和数组学习笔记
- 探索PowerShell (八) 数组、哈希表(附:复制粘贴技巧)
- C#中数组初始化与数组元素复制的方法
- C#交错数组用法实例
- PowerShell数组的一些操作技巧
- C#通过yield实现数组全排列的方法
- C#不重复输出一个数组中所有元素的方法
- C#实现将数组内元素打乱顺序的方法
- mysql binlog二进制日志详解
- Ruby简明教程之数组和Hash介绍
- C语言查找数组里数字重复次数的方法
- C语言柔性数组实例详解
- 详解C++编程中对二进制文件的读写操作
- Perl中怎样从数组中删除某个值?
- 详解C++编程中用数组名作函数参数的方法