统计序列中出现一次的数字

// ConsoleApplication46.cpp : 定义控制台应用程序的入口点。
//统计出现一次的数字(其它数字只出现两次)

#include "stdafx.h"
#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
using namespace std;
unsigned int FirstBitIs1(int num){
	if (num<0 || num>0xffff){
		cout <<"beyond range" << endl;
		return INFINITY;
	}
	int k = 0;
	for (; num % 2 == 0; num /= 2){
		k++;
	}
	return k;
}
//unsigned int FirstBitIs1(int num){
//	int index = 0;
//	while (((num & 1)== 0) && index < 8 * sizeof(int)){
//		num = num >> 1;
//		index++;
//	}
//	return index;
//}
//bool Is1(int num, unsigned int bit){
//	int s = pow(2, bit);
//	return num & s;
//}
bool Is1(int num, unsigned int bit){
	num = num >> bit;
	return (num & 1);
}
void FindNumsAppearOnce(int data[], int length,int *num1,int *num2){
	int i,s=0;
	unsigned int j;
	if (data == NULL && length < 2){
		return;
	}
	for (i = 0; i < length; i++){
		s ^= data[i];
	}
	j = FirstBitIs1(s);
	*num1 = 0;
	*num2 = 0;
	for (i = 0; i < length; i++){
		if (Is1(data[i], j) == 1){
			(*num1) ^= data[i];
		}
		else{
			(*num2) ^= data[i];
		}
	}
	
}
// ====================测试代码====================
void Test(char* testName, int data[], int length, int expected1, int expected2)
{
	if (testName != NULL)
		printf("%s begins: ", testName);

	int result1, result2;
	FindNumsAppearOnce(data, length, &result1, &result2);

	if ((expected1 == result1 && expected2 == result2) ||
		(expected2 == result1 && expected1 == result2))
		printf("Passed.\n\n");
	else
		printf("Failed.\n\n");
}
void Test1()
{
	int data[] = { 2, 4, 3, 6, 3, 2, 5, 5 };
	Test("Test1", data, sizeof(data) / sizeof(int), 4, 6);
}

void Test2()
{
	int data[] = { 4, 6 };
	Test("Test2", data, sizeof(data) / sizeof(int), 4, 6);
}

void Test3()
{
	int data[] = { 4, 6, 1, 1, 1, 1 };
	Test("Test3", data, sizeof(data) / sizeof(int), 4, 6);
}

int _tmain(int argc, _TCHAR* argv[])
{
	Test1();
	Test2();
	Test3();
	/*cout <
      
      
       
       << endl;
	cout <
       
       
         << endl;*/ system("pause"); return 0; } 
       
      
      
     
     
    
    
   
   
题目原意是在数字序列中找出其中只出现一次的数字,而序列中的其他数字出现两次。

可以这样考虑:由于序列中的其它数据出现2次,因此,相同的数字异或运算得到的结果是0,而不同的两数异或得到的二进制结果中某个位上的数字必定为1。异或运算服从交换率,因此,将序列中的数字依次执行异或运算,最后得到的二进制位中最低某位为1,假设该位为m位。很显然,将序列中按第m位为1或0分为2个子序列,出现一次的数字分别位于两个子序列中,两个子序列中的其它数字军出现两次。再次分别将两个子序列中的数字做异或运算,得到的两个结果即为原序列中出现一次的数字。

该方法充分利用异或运算中同一位置二进制数相同为0的性质,出现两次的数字相异的结果为0,最终得出结果。

// ConsoleApplication46.cpp : 定义控制台应用程序的入口点。
//剑指Offer中统计出现一次的数字(其它数字只出现两次)

#include "stdafx.h"
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
unsigned int FirstBitIs1(int num){
	if (num<0 || num>0xffff){
		cout <<"beyond range" << endl;
		return INFINITY;
	}
	int k = 0;
	for (; num % 2 == 0; num /= 2){
		k++;
	}
	return k;
}
//unsigned int FirstBitIs1(int num){
//	int index = 0;
//	while (((num & 1)== 0) && index < 8 * sizeof(int)){
//		num = num >> 1;
//		index++;
//	}
//	return index;
//}
//bool Is1(int num, unsigned int bit){
//	int s = pow(2, bit);
//	return num & s;
//}
bool Is1(int num, unsigned int bit){
	num = num >> bit;
	return (num & 1);
}
void FindNumsAppearOnce(int data[], int length,int *num1,int *num2){
	int i,s=0;
	unsigned int j;
	if (data == NULL && length < 2){
		return;
	}
	for (i = 0; i < length; i++){
		s ^= data[i];
	}
	j = FirstBitIs1(s);
	*num1 = 0;
	*num2 = 0;
	for (i = 0; i < length; i++){
		if (Is1(data[i], j) == 1){
			(*num1) ^= data[i];
		}
		else{
			(*num2) ^= data[i];
		}
	}
	
}
// ====================测试代码====================
void Test(char* testName, int data[], int length, int expected1, int expected2)
{
	if (testName != NULL)
		printf("%s begins: ", testName);

	int result1, result2;
	FindNumsAppearOnce(data, length, &result1, &result2);

	if ((expected1 == result1 && expected2 == result2) ||
		(expected2 == result1 && expected1 == result2))
		printf("Passed.\n\n");
	else
		printf("Failed.\n\n");
}
void Test1()
{
	int data[] = { 2, 4, 3, 6, 3, 2, 5, 5 };
	Test("Test1", data, sizeof(data) / sizeof(int), 4, 6);
}

void Test2()
{
	int data[] = { 4, 6 };
	Test("Test2", data, sizeof(data) / sizeof(int), 4, 6);
}

void Test3()
{
	int data[] = { 4, 6, 1, 1, 1, 1 };
	Test("Test3", data, sizeof(data) / sizeof(int), 4, 6);
}

int _tmain(int argc, _TCHAR* argv[])
{
	Test1();
	Test2();
	Test3();
	/*cout <<FirstBitIs1(8) << endl;
	cout <<Is1(14,5) << endl;*/
	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值