統計序列中出現一次的數字
阿新 • • 發佈:2019-02-06
題目原意是在數字序列中找出其中只出現一次的數字,而序列中的其他數字出現兩次。// 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; }