1 單身狗
在一個整型數組中,只有一個數字出現一次,其他數組都是成對出現的,請找出那個只出現一次的數字。
例如:數組中有:1 2 3 4 5 1 2 3 4,只有5出現一次,其他數字都出現2次,找出5
需要用到的知識:
按位異或 ^ 將其第一操作數的每個位(補碼)與其第二操作數的相應位進行比較。如果其中一個操作數中的位為 0,而另一個操作數中的位為 1,則相應的結果位設置為 1(即標記不同)。 否則,將對應的結果位設置為 0。(該運算符的兩個操作數必須為整型類型)
按位異或運算有以下有趣的特點:
//1. a ^ a = 0
//2. 0 ^ a = a
//3. 3 ^ 3 ^ 5 = 5
// 3 ^ 5 ^ 3 = 5 即支持交換律
由於數組中除5外其他數字均成對出現,而按位異或運算中相同數字的結果為0,我們可以利用這一特性找出單獨的數字。
代碼實現:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int Func(int arr[], int len)
{
int ret = 0;
for (int i = 0; i < len; i++)
{
ret ^= arr[i];//對arr數組的每一個值,按位異或
}
return ret;
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4 };
int len = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", Func(arr, len));
return 0;
}
運行結果:
2 交換兩個變量(不創建臨時變量)
不允許創建臨時變量,交換兩個整數的內容
需要用到的知識:
先演示一種方法。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 1;
int b = 5;
printf("交換前:%d %d\n", a, b);
a = a + b;//可能溢出
b = a - b;//b = (a + b) - b = a
a = a - b;//a = (a + b) - a = b
printf("交換後:%d %d\n", a, b);
return 0;
}
由於存在a = a + b,當a、b的值過大時可能會溢出。按位異或 **^**能很好的解決這個問題,因為其直接操作的是a、b的二進制碼。(提醒:這種方法只能針對整數交換且可讀性不高、效率不高)
代碼實現:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 1;
int b = 5;
printf("交換前:%d %d\n", a, b);
a = a ^ b;
b = a ^ b;//b = (a ^ b) ^ b = a
a = a ^ b;//a = (a ^ b) ^ a = b
printf("交換後:%d %d\n", a, b);
return 0;
}
運行結果:
3 統計二進制中1的個數
寫一個函數返回參數二進制中 1 的個數。
比如: 15 0000 1111 4個1
需要用到的知識:按位與&,移位操作符<<、>>
代碼實現:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//法1
int main()
{
int num = 15;
int count = 0;
for (int i = 0; i < 32; i++)
{
if ((num >> i) & 1)
count++;
}
printf("%d\n", count);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//法2
int main()
{
int num = 15;
int count = 0;
while (num)
{
count++;
num = num & (num - 1);//關鍵點
}
printf("%d\n", count);
return 0;
}
4 二進制位置0或者置1
編寫代碼將13二進制序列的第5位修改為1 ,然後再改回0
13 的 2 進制序列: 00000000 00000000 00000000 00001101
將第 5 位置為 1 後: 00000000 00000000 00000000 00011101
將第 5 位再置為 0 : 00000000 00000000 00000000 00001101
需要用到的知識:按位與&,按位或|,按位取反~,移位操作符<<、>>
代碼實現:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 13;
a = a | (1 << 4);
printf("%d\n", a);
a = a & ~(1 << 4);
printf("%d\n", a);
return 0;
}
5 打印整數二進制的奇數位和偶數位
獲取一個整數二進制序列中所有的偶數位和奇數位,分別打印出二進制序列
需要用到的知識:按位與&,移位操作符<<、>>
代碼實現:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 13;
//13 00000000 00000000 00000000 00001101
//1 00000000 00000000 00000000 00000001
printf("13的二進制偶數位:");
// 0010
for (int i = 31; i >= 0; i-=2)
{
printf("%d ", (a>>i) & 1);
}
printf("\n");
printf("13的二進制奇數位:");
// 0011
for (int i = 30; i >= 0; i -= 2)
{
printf("%d ", (a >> i) & 1);
}
printf("\n");
return 0;
}
6 求兩個數二進制中不同位的個數
編程實現:兩個int(32位)整數m和n的二進制表達中,有多少個位(bit)不同?
輸入例子:1999 2299
輸出例子:7
需要用到的知識:按位異或 ^,按位與&,第3題
代碼實現:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 1999;
int b = 2299;
int c = a ^ b;
int count = 0;
while (c)
{
count++;
c = c & (c - 1);
}
printf("%d\n", count);
return 0;
}