一、力扣題目
1、題目本體
2、題解
本題目我們使用異或分組的方法來解決。可以在我之前的文章《C語言——操作符CSDN博客》中看一下異或的特點。
由于異或的運算規則為相同為0,不同為1,而且是在二進制補碼上進行操作的,我們可以發現的一個特點就是相同的數字異或的結果是0,利用這一點,我們好像就對上面的題目有了些許想法。
對于整個數組,只有兩個出現一次的數字,其他的數字都是出現兩次的,所以們可以發現,如果我們將數組所有的元素都異或起來,結果就是兩個只出現一次的兩個數字異或起來的結果。就像下面:
int res = 0;int i = 0;for (i = 0; i < numsSize; i++) {res ^= nums[i];}
然后我們得到的這個res就是可以反映這兩個只出現一次的數字的不同的位的,下面舉個例子:
假設兩個只出現一次的數字是 5 和 6,它們的二進制為101和110,異或后得到的結果的二進制為011。然后我們得到這個結果的目的就是將這兩個不同的數字分開,可以發現結果中為 1 的位,也是這兩個數字的不同的位,我們可以直接取到結果中第一個為1的位,通過這個位來將兩個數分在不同組中,然后分別將兩個組異或起來,就可已得到這兩個數字。
3、代碼
int* singleNumber(int* nums, int numsSize, int* returnSize) {int res = 0;int i = 0;for (i = 0; i < numsSize; i++) {res ^= nums[i];}int pos = 0;for (pos = 0; pos < 32; pos++) {if (((res >> pos) & 1) == 0) {break;}}int num1 = 0;int num2 = 0;for (i = 0; i < numsSize; i++) {if (((nums[i] >> pos)& 1) == 0) {num1 ^= nums[i];}else {num2 ^= nums[i];}}int* ans = (int*)malloc(2 * sizeof(int));ans[0] = type1;ans[1] = type2;*returnSize = 2;return ans;
}
4、解釋
for (i = 0; i < numsSize; i++) {res ^= nums[i];}
將數組中所有元素異或起來,得到 res 。
for (pos = 0; pos < 32; pos++) {if (((res >> pos) & 1) == 0) {break;}}
用來找到 res 中第一個為1的位,然后使用 pos 變量來保存這個位是第幾位,以便后面使用。
int num1 = 0;int num2 = 0;for (i = 0; i < numsSize; i++) {if (((nums[i] >> pos)& 1) == 0) {num1 ^= nums[i];}else {num2 ^= nums[i];}}
這一步完成分組和分別將兩個組的元素都異或起來,兩步合在了一起。
if (((nums[i] >> pos)& 1) == 0) {num1 ^= nums[i];}
如果數組中的元素的 pos 位也為 1 的話就分一組,然后依次異或起來,這時那兩個只出現一次的數字已經被分開,這里只有其中之一。
else {num2 ^= nums[i];}
如果數組中的元素的 pos 位0為 0 的話就分一組,然后依次異或起來,0,這里只有其中另一。
這樣的活,其他相同的數字被分到哪一組都無所謂,它們兩個一對會被分到一組,因為兩個相同的數字的同一位是相同的。這樣異或起來,最后,num1 和 num2 中就剩下那兩個只出現一次的數字了。
二、模擬實現atoi函數
1、atoi函數介紹
在C語言中,atoi
(ASCII to Integer)是一個標準庫函數,用于將表示整數的字符串轉換為其對應的整數值。該函數定義在stdlib.h
頭文件中。
函數原型
int atoi(const char *str);
參數
str
:指向一個以空字符('\0'
)結尾的字符串,該字符串表示一個整數。
參數
返回轉換后的整數值。
如果字符串中不包含合法的整數,atoi
的行為未定義,可能返回0或其他值。
2、模擬實現
#include <stdio.h>
#include <limits.h>int my_atoi(const char* str) {const char* string = str;while (*string == ' ') {//跳過前置空格string++;}int flag = 0;if (*string == '-') {//判斷數字正負flag = -1;string++;}else if (*string == '+') {flag = 1;string++;}long long retValue = 0;while (*string) {//計算數字本體if (*string <= '9' && *string >= '0') {retValue = retValue * 10 + (long long)((*string - '0') * flag);if (retValue > INT_MAX || retValue < INT_MIN) {//判斷是否越界return 0;}}else {return (int)retValue;}string++;}return (int)retValue;
}int main() {char str[] = " -123878";int res = my_atoi(str);printf("%d", res);return 0;
}
運行結果: