福建建设银行网站delphi网站开发教程

当前位置: 首页 > news >正文

福建建设银行网站,delphi网站开发教程,宝安住房和建设局网站官网,wordpress CodeMirror【C语言刷题】——初识位操作符 位操作符介绍题一、 不创建临时变量#xff08;第三个变量#xff09;#xff0c;实现两个数的交换#xff08;1#xff09;法一#xff08;2#xff09;法二 题二、 求一个数存储在内存中的二进制中“一”的个数#xff08;1#xff0… 【C语言刷题】——初识位操作符 位操作符介绍题一、 不创建临时变量第三个变量实现两个数的交换1法一2法二 题二、 求一个数存储在内存中的二进制中“一”的个数1法一2法二3法三 题三、 单身狗11法一2法二 题四、 单身狗二1法一2法二3法三 位操作符介绍 位操作符有 //左移操作符//右移操作符//按位与 | //按位或 ^ //按位异或 ~ //按位取反注他们的操作数必须是整数。 更多关于位操作符介绍请看这篇文章【C语言】——详解操作符上 题一、 不创建临时变量第三个变量实现两个数的交换 1法一 参考代码 #includestdio.hint main() {int a 0;int b 10;a a b;b a - b;a a - b;printf(交换后a %d b %d\n, a, b);return 0; }代码讲解 相信这段代码大家都能看懂这里我就不多解释了。      但遗憾的是这个方法有一点问题当 a 和 b 的值很大但都不超过 i n t int int 的存储空间时他们相加会超过 int 的存储空间导致丢失数据。      那有什么更好的办法吗有的请看法二。 2法二 参考代码 #includestdio.hint main() {int a 0;int b 10;a a ^ b;b a ^ b;a a ^ b;printf(交换后a %d b %d, a, b);return 0; }代码讲解 首先我们需掌握几个知识点 一个数与他自身异或为 0 0 0 即 a a a ^ a a a 0 0 0任何数与 0 0 0 异或结果都为其本身即 a a a ^ 0 0 0 0 0 0异或运算满足交换律即 a a a ^ a a a ^ b b b a a a ^ b b b ^ a a a 第八行代码b a ^ b;由于第七行代码a a ^ b; 此时a a ^ b;即b a ^ b ^ b得b a ^ 0 得 b a 同理第九行代码a a ^ b;由于第七行代码a a ^ b; 和第八行代码结果b a即a a ^ b ^ a,得 a b。 我们可以这样来理解我们把第七行代码a a ^ b;当成是一把钥匙碰到 a 得 b 碰到 b 得 a 。 题二、 求一个数存储在内存中的二进制中“一”的个数 1法一 参考代码 #include stdio.hint main() {int num 0;scanf(%d, num);int count 0;//计数while (num){if (num % 2 1)count;num num / 2;}printf(二进制中1的个数 %d\n, count);return 0; }代码讲解 其实该法的解题思路与在十进制中打印每一位是思路相同。在十进制中要想获得每一位我们的方法是先余十再除十不断循环。这里也是一样的只是因为是二进制改为先余二再除而不断循环遇到结果为 1 则计数器加一。      但是这个方法有点问题它只能处理正数的情况如果是负数他就没办法了。为什么因为ifnum % 2 1负数余二永远不可能为 1但num num / 2;语句正常执行输入复数的结果永远是 0。 2法二 参考代码 #includestdio.hint main() {int n 0;scanf(%d, n);int count 0;for (int i 0; i 32; i){if (n 1){count;}n n 1;}printf(%d, count);return 0; }代码讲解 法二的思路是给这个数的每一位都与上 1 不断右移因为与的逻辑是有 0 为 0全 1 为 1。当运算结果为 0 表示该位为 0 结果为 1 该位为 1    图解以5为例 结果为1计数器加一    5右移一位 结果为0计数器不变    5再右移 结果为1计数器加一    接着不断右移一共32次因为后面的结果都是0变不再一一赘述。      但该方法一定要循环32次有没有效率更高的方法呢 3法三 参考代码 #includestdio.hint main() {int n 0;scanf(%d, n);int count 0;while (n){n n (n - 1);count;}printf(%d, count);return 0; }代码讲解 该方法的核心这个数本身与他自身减一做 与 运算不断循环    n n (n - 1);或许大家一脸疑惑别急直接上图 以15为例 循环一次 循环两次 循环三次 循环四次 大家发现没有每循环一次就会把最右边的 1 给消去当最终把所有 1 消去变成零循环结束而我们只需要计算循环了多少次就能知道该数有几个 1 。 题三、 单身狗1 题目 在一个整型数组中只有一个数字出现一次其他数组都是成对出现的请找出那个只出现一次的数字。    例如   数组中有1 2 3 4 5 1 2 3 4只有5出现一次其他数字都出现2次找出5 1法一 参考代码 #includestdio.hint main() {int arr[] { 1, 2, 3, 4, 5, 1, 2, 3, 4 };int sz sizeof(arr) / sizeof(arr[0]);for (int i 0; i sz; i){int flag 0;int n 0;for (int j 0; j sz; j){if (i j)continue;n arr[i] ^ arr[j];if (n 0){flag 1;break;}}if (flag 0)printf(单身狗是%d\n, arr[i]);}return 0; }代码讲解 该方法想必大家都很容易想到逻辑也很简单遍历数组中的每一个数每个数再遍历一遍除自身外的整个数组遇到与自身一样的数就说明自己不是单身狗。   这里就不再过多解释 2法二 参考代码 int main() {int arr[] { 1, 2, 3, 4, 5, 1, 2, 3, 4 };int sz sizeof(arr) / sizeof(arr[0]);int a 0;for (int i 0; i sz ; i){a arr[i] ^ a;}printf(单身狗是%d\n, a);return 0; }解题思路 这里再带大家重温一下按位异或的相关知识 1一个数与他自身异或为 0 0 0 即 a a a ^ a a a 0 0 0 2任何数与 0 0 0 异或结果都为其本身即 a a a ^ 0 0 0 0 0 0 那么综合运用起来就是这题的解法啦 将数组元素全部异或    a 1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 1 ^ 2 ^ 3 ^ 4 a 1 ^ 1 ^ 2 ^ 2 ^ 3 ^ 3 ^ 4 ^ 4 ^ 5 a 0 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0 ^ 0 ^ 5 a 5 题四、 单身狗二 题目 一个数组中只有两个数字是出现一次其他所有数字都出现了两次。 编写一个函数找出这两个只出现一次的数字。    例如 有数组的元素是1234512346 只有5和6只出现1次要找出5和6. 1法一 参考代码: #includestdio.hint main() {int arr[] { 1, 2, 3, 4, 5, 1, 2, 3, 4,6 };int sz sizeof(arr) / sizeof(arr[0]);int count 0;for (int i 0; i sz; i){int flag 0;int n 0;for (int j 0; j sz; j){if (i j)continue;n arr[i] ^ arr[j];if (n 0){flag 1;}}if (0 flag){printf(单身狗是%d\n, arr[i]);count;}if (2 count)break;}return 0; }代码讲解: 这段代码的思路与上一题单身狗一的法一思路是相同的      即依次取出数组中的每个元素让他与数组中剩下的元素比较当遍历完整个数组依然没找到相同的数时说明他是其中一个单身狗计数器 1 并打印当计数器为二时说明已找到全部单身狗退出循环。 2法二 参考代码: #includestdio.hint main() {int arr[] { 1,2,3,4,5,1,2,3,4,6 };int sz sizeof(arr) / sizeof(arr[0]);int i 0;for (i 0; i 32; i){int j 0;int last_0 0;int last_1 0;for (j 0; j sz; j){if ((arrj) 0){last_0 ^ arr[j];}else if ((arrj) ! 1){last_1 ^ arr[j];}}if(last_0 ! 0 last_1 ! 0){printf(%d %d, last_0, last_1);break;}}return 0; }代码讲解: 做了上面的单身狗我们想这题应该也可以用异或分方法来解      我们想到如果将所有元素直接异或肯定是无法直接找出两只单身狗这时我们可以想到先将他们分组让每一组都只有一只单身狗再将两组全部异或就行了。那么怎么分组呢      我们看到因为数组两两元素相同加上两只单身狗所以数组总数一定是偶数这时我们可以依次遍历数组中所有元素的二进制位数将该位为 1 和为 0 的元素分成两组分完组后若两组的元素个数都为奇数相同的数该位一定相同一定被分到同一组剩下一只单身狗为奇数则成功将两只单身狗分开再分别异或两组中的所有元素就能找出两周单身狗啦      如果分完组两边都是偶数则比较二进制下一位直到分出奇数组。 3法三 参考代码: #includestdio.hvoid findTwoNum(int arr[], int n, int * pnum1, int * pnum2) {int i;int sum 0; ​for (i 0; i 9; i){sum ^ arr[i];} //先找到两个数互相异或的结果 ​int pos;for (i 0; i 32; i){if (sum 1 i){pos i;break;}} //再找到有分歧的一位。在这一位上两个数一定是一个1一个0 ​*pnum1 *pnum2 0;for (i 0; i 10; i){if (arr[i] 1 pos){*pnum1 ^ arr[i]; //这一位是1的放在数1里}else{*pnum2 ^ arr[i]; //这一位是0的放在数2里}} }代码讲解: 法二虽然用到了异或操作但分起组来太过麻烦效率并不高有没有什么方法能实现快速分组呢答案当然是有的。 我们知道两个相同的数异或为 0将数组中的所有元素异或起来得到的结果就是两只单身狗异或的结果。         这时我们可能就要问了那得到这个结果有什么用呢肯定不止唯二这两个数异或才得出这个结果其他两个数异或也有可能得到这个结果。 确实如此但我们别忘了异或的特点相同为 0相异为 1。我们只需要找到异或的结果的其中一个为“ 1 ”的位数这说明在这个位其中一只单身狗是0另一只为1。 这时我们只需要将数组中的元素分两组:一组的元素在该位的值为 0另一组该位值为 1再将两组的所有元素分别异或起来自然就得到两只单身狗啦。怎么样是不是很巧妙呢。