1. 程式人生 > >統計序列中出現一次的數字

統計序列中出現一次的數字

// 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 <
題目原意是在數字序列中找出其中只出現一次的數字,而序列中的其他數字出現兩次。

可以這樣考慮:由於序列中的其它資料出現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;
}