int func(int x)
{
int count = 0;
while (x)
{
count++;
x = x&(x - 1);//与运算
}
return count;
}
A: 死循环 B: 64 C: 32 D: 16
解析 C
-1 原码 1000000 00000000 00000000 00000001
其补码 1111111 11111111 11111111 11111111-2 原码 1000000 00000000 00000000 00000010
反码 1111111 11111111 11111111 11111101
补码 1111111 11111111 11111111 11111110-1&-2 1111111 11111111 11111111 11111110
首位不变,其他取反+1其原码为-2-3 原码 1000000 00000000 00000000 00000011
反码 1111111 11111111 11111111 11111100
补码 1111111 11111111 11111111 11111101-2&-3 1111111 11111111 11111111 11111100
首位不变,其他取反+1其原码为-4可以看出每次异或都将最后的一位变为0,那么进行32次,全部变为0,跳出while循环 count=32;
int count = 0;
int x = -1;
while(x)
{
count++;
x = x >> 1;
}
printf("%d",count);
解析 D
-1 补码 11111111 11111111 11111111 11111111
x>>1 11111111 11111111 11111111 11111111
左移最高位补的是符号位,因此-1的符号位是1,所以最高位衡补1,造成死循环
A: a = (b = (c = 2 , d = 3)) B: i++ C: a/b = 2 D: a = a < a + 1
解析 C
A:先看逗号表达式 d=3 将d的值给b 再将b的值给a
B:i++最常见的一种写法
C:a/b不能作为一个变量
D:a < a + 1的结果为1(真),否则为0(假)。最后将这个结果赋给a变量。
A: 1 B: 2 C: 3 D: 4
解析 A
w
判断 (为真) ( 为假)
首先,计算w < x,即1 <2,这个条件为真,所以返回w的值,即1。
以最外层的表达式为主。
int main()
{
int a=1,b=2,m=0,n=0,k;
k=(n=b<a)&&(m=a);
printf("%d,%d\n",k,m);
return 0;
}
A: 0,0 B: 0,1 C: 1,0 D: 1,1
解析 A
核心代码版:
int Add(int a, int b )
{
while (b != 0)
{
int sum = a ^ b;
int carry = (a & b) << 1;
a = sum;
b = carry;
}
return a;
}
完整代码版:
#define _CRT_SECURE_NO_WARNINGS 1
#include
int Add(int a, int b)
{
while (b != 0)
{
int sum = a ^ b;
int carry = (a & b) << 1;
a = sum;
b = carry;
}
printf("%d", a);
}
int main()
{
int a = 0, b = 0;
scanf("%d %d", &a, &b);
Add(a, b);
return 0;
}
解析:
- while 循环:进入循环后,我们将会一直执行下去,直到 b 的值变为 0。
- 异或操作:int sum = a ^ b;,我们通过异或操作(^)得到两个整数的无进位和。 例如,对于二进制数 5 和 3(101 和 011),异或操作将会得到二进制数 6(110)。
- 与操作和左移操作:int carry = (a & b) << 1;,我们通过与操作(&)和左移操作(<<)得到了两个整数的进位值。与操作将会得到两个整数的公共位,并且左移操作将将这些公共位移到正确的位置上。
例如,对于二进制数 5 和 3(101 和 011),与操作将会得到二进制数 1(001),然后左移操作将会得到二进制数 2(010)。- 更新 a 和 b:a = sum; b = carry;,我们将无进位和和进位值分别赋给了 a 和 b。这样,a 的值变为了无进位和,b 的值变为了进位值,为下一次循环做准备。
- 继续执行下一次循环,直到 b 的值变为 0。每次循环都会将进位值不断地传递下去,直到没有进位为止。通过这个循环过程,我们实际上是将加法拆分成了无进位和和进位值的计算,并且通过循环迭代将进位值不断地传递下去。最后,我们得到的
a 的值就是两个整数的和。- 返回 a:当 b 的值变为 0 时,我们跳出循环并返回 a,它的值就是两个整数的和。
如果看了解析还是不太明白的话,大家自己在纸上拿两个数字运算一边就可以明白啦,毕竟还是要动动手的嘛。
示例 1: 输入:nums = [4,3,2,7,8,2,3,1] 输出:[5,6]
示例 2: 输入:nums = [1,1] 输出:[2]
核心代码版:
#define _CRT_SECURE_NO_WARNINGS 1
#include
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
{
int* res = (int*)malloc(sizeof(int) * numsSize);
int i, j = 0;
for (i = 0; i < numsSize; i++)
{
res[i] = 0;
}
for (i = 0; i < numsSize; i++)
{
res[nums[i] - 1] = res[nums[i] - 1]+1;
}
for (i = 0; i < numsSize; i++)
{
if (res[i] == 0) res[j++] = i + 1;
*returnSize = j;
}
return res;
}
完整代码版:
#define _CRT_SECURE_NO_WARNINGS 1
#include
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
{
int* res = (int*)malloc(sizeof(int) * numsSize);
int i, j = 0;
for (i = 0; i < numsSize; i++)
{
res[i] = 0;
}
for (i = 0; i < numsSize; i++)
{
res[nums[i] - 1] += 1;
}
for (i = 0; i < numsSize; i++)
{
if (res[i] == 0) res[j++] = i + 1;
*returnSize = j;
}
return res;
}
int main()
{
int n = 0;
scanf("%d", &n);
int nums[10001] = { 0 };
for (int i = 0; i < n; i++)
{
scanf("%d", &nums[i]);
}
int returnSize;
int* result = findDisappearedNumbers(nums, n, &returnSize);
printf("消失的数字:");
for (int i = 0; i < returnSize; i++)
{
printf("%d ", result[i]);
}
printf("\n");
free(result); // 释放内存
return 0;
}
解析:
主函数的部分非常简单,就是定义数组和数组长度,相信大家都能看懂,我就不在这里讲啦!
在核心代码中,使用malloc函数,这个函数大家不理解的话可以看我之前的博客哦,就是开辟一块空间。
①首先,定义了一个长度为numsSize的整型数组res,并将其初始化为0。②然后,遍历nums数组,将对应的res数组位置上的数值加1。这一步的目的是统计每个数字出现的次数。
nums[i]表示nums数组中的第i个元素的值。
nums[i]-1表示将该元素值减1,目的是将其作为res数组的索引值,因为数组的索引从0开始。
res[nums[i]-1]=res[nums[i]-1]+1表示将res数组中相应索引位置的值加1。这个操作是在进行计数统计。
.③接下来,再次遍历res数组,如果某个位置上的数字为0,说明该位置对应的数字在nums数组中缺失。将该缺失的数字添加到返回的数组之中。
遍历数组res的每一个元素,从下标0到numsSize-1。
如果res的当前元素值为0,表示该位置缺失了一个数。
将i+1赋值给res中下标为j的位置,然后将j的值加1。
最后,将j赋值给returnSize,表示缺失数的个数。
.④最后,将返回的数组长度记录在returnSize指针所指的位置,并将res数组返回。