1.一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
找出这两个数字,编程实现。
(1)原始作法:我们通过两重循环,逐次的对数组进行遍历.
#include <stdio.h>
#include <windows.h>
//找单独出现的数,一般方法
int search(int a[], int len)
{
int i, j, k;
for (i = 0; i < len; i++) {
k = 0;
for (j = 0; j < len; j++) {
if (a[j] == a[i]) {
k++;
}
}
if(k == 1){
printf("%d ", a[i]);
}
}
printf("\n");
}
int main()
{
int a[] = { 1,3,5,6,1,3,5,7 };
int len = sizeof(a) / sizeof(a[0]);
search(a, len);
system("pause");
return 0;
}
(2)用异或运算来解题,首先看一下异或的特点:
1.0^0=0,0^1=1,1^0=1,1^1=0,即相同取0,不同取1,那么相同的两个整数异或结果为0,任何整数与0异或都等于其本身
2.异或满足交换律,即a^b^c=a^c^b
所以,将数组中的数从头到尾依次异或,出现偶数次的数异或都为0,最终结果是两个只出现一次的数字异或的结果,由于这两个数字不同,异或的结果一定不为0,即其二进制表示形式中一定存在某一位为1,找到第一个为1的位,假设是第N位,那么在对应的这一位上,这两个数一个为0,一个为1,根据第N位是否为1,将原数组分成两个子数组,这两个子数组分中都只包含一个只出现了一次的数,其他的数都出现了两次,两个子数组中的元素分别异或,就得到了两个只出现一次的数。
#include <stdio.h>
#include <windows.h>
void search(int arr[], int len)
{
int ret = 0;
int inter = 0;
int result1 = 0;
int result2 = 0;
for (int i = 0; i < len; i++)
{
ret ^= arr[i];
}
/*找ret最右边的1*/
inter = ret - (ret&(ret - 1));
for (int i = 0; i < len; i++)
{
int a = (arr[i] >> (inter - 1)) % 2; //取出arr[i]的第inter位
if (a == 0)
{
result1 ^= arr[i];
}
else
{
retsult2 ^= arr[i];
}
}
printf("出现奇数次的两个数为: %d,%d\n", result1, result2);
}
int main()
{
int arr[] = { 1, 3, 5, 6, 1, 3, 5, 7 };
int len = sizeof(arr) / sizeof(arr[0]);
search(arr, len);
system("pause");
return 0;
}
2.喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水。编程实现。
#include <stdio.h>
#include <Windows.h>
int drinkNum(int n)
{
int count = n;
while (n > 1)
{
count = count + n / 2;
n = n / 2 + n % 2;
}
return count;
}
int main()
{
int n = 20;
int ret = drinkNum(n);
printf("%d\n", ret);
system("pause");
return 0;
}
3. 模拟实现strcpy
char *my_strcpy(char *dest, const char *src)
{
char *ret = dest;
assert(dest);
assert(src);
while (*dest = *src)
{
dest++, src++;
}
return ret;
}
4.
模拟实现strcat
char *my_strcat(char *dest, const char *src)
{
char *ret = dest;
assert(dest);
assert(src);
while (*dest)
{
dest++;
}
while (*dest = *src)
{
dest++, src++;
}
return ret;
}