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

【C语言刷题】——初识位操作符

【C语言刷题】——初识位操作符

    • 位操作符介绍
    • 题一、 不创建临时变量(第三个变量),实现两个数的交换
      • (1)法一
      • (2)法二
    • 题二、 求一个数存储在内存中的二进制中“一”的个数
      • (1)法一
      • (2)法二
      • (3)法三
    • 题三、 单身狗1
      • (1)法一
      • (2)法二
    • 题四、 单身狗二
      • (1)法一
      • (2)法二
      • (3)法三

位操作符介绍

位操作符有:

<<      //左移操作符
>>      //右移操作符
&       //按位与
|       //按位或
^       //按位异或
~       //按位取反

  注:他们的操作数必须是整数。

  更多关于位操作符介绍请看这篇文章:【C语言】——详解操作符(上)

题一、 不创建临时变量(第三个变量),实现两个数的交换

(1)法一

  
参考代码:

#include<stdio.h>int 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)法二

  
参考代码:

#include<stdio.h>int 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.h>int 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 ,则计数器加一。
  
  但是这个方法有点问题:它只能处理正数的情况,如果是负数,他就没办法了。为什么?因为:if(num % 2 == 1),负数余二永远不可能为 1,但num = num / 2;语句正常执行,输入复数的结果永远是 0。

  

(2)法二

  
参考代码:

#include<stdio.h>int 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)法三

  
参考代码:

#include<stdio.h>int 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)法一

  
参考代码:

#include<stdio.h>int 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

题四、 单身狗二

  
题目:

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这两个只出现一次的数字。

  
例如:

有数组的元素是:1,2,3,4,5,1,2,3,4,6

只有5和6只出现1次,要找出5和6.

  

(1)法一

参考代码:

#include<stdio.h>int 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)法二

参考代码:

#include<stdio.h>int 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 ((arr[j] & (1 << i)) == 0){last_0 ^= arr[j];}else if ((arr[j] & (1 << i)) != 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)法三

参考代码:

#include<stdio.h>void 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,再将两组的所有元素分别异或起来,自然就得到两只单身狗啦。怎么样,是不是很巧妙呢。

相关文章:

【C语言刷题】——初识位操作符

【C语言刷题】——初识位操作符 位操作符介绍题一、 不创建临时变量&#xff08;第三个变量&#xff09;&#xff0c;实现两个数的交换&#xff08;1&#xff09;法一&#xff08;2&#xff09;法二 题二、 求一个数存储在内存中的二进制中“一”的个数&#xff08;1&#xff0…...

Python 对Excel工作表中的数据进行排序

在Excel中&#xff0c;排序是整理数据的一种重要方式&#xff0c;它可以让你更好地理解数据&#xff0c;并为进一步的分析和报告做好准备。本文将介绍如何使用第三方库Spire.XLS for Python通过Python来对Excel中的数据进行排序。包含以下三种排序方法示例&#xff1a; 按数值…...

Python对头发二维建模(考虑风力、重力)

目录 一、背景 二、代码 一、背景 数值方法被用于创建电影、游戏或其他媒体中的计算机图形。例如&#xff0c;生成“逼真”的烟雾、水或爆炸等动画。本文内容是对头发的模拟&#xff0c;要求考虑重力、风力的影响。 假设&#xff1a; 1、人的头部是一个半径为10厘米的球体。…...

Python基础快速入门

Python基础快速入门 前置知识 Python Python是一种广泛使用的高级编程语言&#xff0c;以其易于学习和使用的语法而闻名。以下是Python的一些主要特点&#xff1a; 高级语言&#xff1a;Python是一种高级语言&#xff0c;这意味着它提供了较高层次的抽象&#xff0c;使编程更…...

C++的学习

代码练习 输入一个字符串&#xff0c;统计其中大写字母、小写字母、数字、空格以及其他字符的个数 #include <iostream>using namespace std;int main() {cout << "请输入一个字符串" << endl;string str;getline(cin,str);int capital 0;int l…...

工地安全反光衣穿戴监测报警摄像机

工地安全反光衣穿戴监测报警摄像机是为了提高工地施工人员的安全意识和监管效率而设计的。这种设备结合了反光衣、监测系统和报警摄像机的功能&#xff0c;可以有效减少工地事故的发生。 首先&#xff0c;工地安全反光衣是一种具有高度可见度的服装&#xff0c;能够使穿戴者在夜…...

UNIAPP微信小程序中使用Base64编解码原理分析和算法实现

为何要加上UNIAPP及微信小程序&#xff0c;可能是想让检索的翻围更广把。&#x1f607; Base64的JS原生编解码在uni的JS引擎中并不能直接使用&#xff0c;因此需要手写一个原生的Base64编解码器。正好项目中遇到此问题&#xff0c;需要通过URLLink进行小程序跳转并携带Base64参…...

人工智能|机器学习——K-means系列聚类算法k-means/ k-modes/ k-prototypes/ ......(划分聚类)

1.k-means聚类 1.1.算法简介 K-Means算法又称K均值算法&#xff0c;属于聚类&#xff08;clustering&#xff09;算法的一种&#xff0c;是应用最广泛的聚类算法之一。所谓聚类&#xff0c;即根据相似性原则&#xff0c;将具有较高相似度的数据对象划分至同一类簇&#xff0c;…...

注意力、自注意力和多头注意力的区别

本文作者&#xff1a; slience_me 注意力、自注意力和多头注意力的区别 理解注意力&#xff08;Attention&#xff09;、自注意力&#xff08;Self-Attention&#xff09;和多头注意力&#xff08;Multi-Head Attention&#xff09;之间的区别非常重要&#xff0c;因为它们是自…...

FTP,SFTP,FTPS,SSL,TSL简介,区别,联系,使用场景说明

文章目录 简介FTPFTPSSFTP加密场景选择FTPS还是SFTPFTP、SFTP、FTPS区别、联系和具体使用场景如何使用FTP、SFTP和FTPSSSLTLSSSL和TLS区别和联系&#xff0c;以及使用场景SSL和TLS技术上的区别一些问题隐式的TLS&#xff08;FTPS/SSL&#xff09;或者显式的TLS&#xff08;FTPS…...

路由算法与路由协议

路由选择协议的核心是路由算法&#xff0c;即需要何种算法来获得路由表中的各个项目。 路由算法的目的很简单&#xff1a;给定一组路由器以及连接路由器的链路&#xff0c;路由算法要找到一条从源路由器到目标路由器的最佳路径。通常&#xff0c;最佳路径是指具有最低费用的路…...

dubbo接口自动化用例性能优化

前言 去年换了一个新部门&#xff0c;看了下当前的自动化用例的情况&#xff0c;发现存在三类性能问题&#xff1a; 本地调试运行时等待时间较长&#xff0c;就算是一个简单的case&#xff0c;执行时间都需要1分钟以上单用例执行时间比较长&#xff0c;部分用例执行时间超过2…...

.net core框架

ASP.NET Core 入门 跨平台开源框架 B/S 类与方法 Console 部分称为“类”。 类“拥有”方法&#xff1b;或者可以说方法存在于类中。 WriteLine() 部分称为“方法”。 想要使用方法就要知道方法在哪里 —————————— 执行流 一次执行一段 ASP.NET Core 是什么东西…...

学习大数据,所需要Java基础(9)

文章目录 网络编程实现简答客户端和服务器端的交互编写客户端编写服务端 文件上传文件上传客户端以及服务器端实现文件上传服务器端实现&#xff08;多线程&#xff09;文件上传服务器端&#xff08;连接池版本&#xff09;关闭资源工具类 BS架构服务器案例案例分析BS结构服务器…...

Python元组(Tuple)深度解析!

目录 1. 什么是元组&#xff1f; 2. 创建元组 3.访问元组 4.元组的运算 5.修改元组不可行 6.元组的应用场景 前面的博客里&#xff0c;我们详细介绍了列表&#xff08;List&#xff09;这一种数据类型&#xff0c;现在我们来讲讲与列表相似的一种数据类型&#xff0c;元组…...

排序 Comparable接口、Comparator接口

String类的Comparable接口 1、String类实现了Comparable<String>接口&#xff0c;并提供了compareTo方法的实现&#xff0c;因此&#xff0c;字符串对象&#xff08;即String类型的实例&#xff09;可以直接调用compareTo()方法来比较它们。2、String类的compareTo()方法…...

得帆助力大族激光主数据平台建设,用数据为企业生产力赋能

本期客户 大族激光科技产业集团股份有限公司&#xff08;以下简称“大族激光”&#xff09;是一家从事工业激光加工设备与自动化等配套设备及其关键器件的研发、生产、销售&#xff0c;激光、机器人及自动化技术在智能制造领域的系统解决方案的优质提供商&#xff0c;是国内激光…...

实名认证电子签署:防范合同纠纷,提升交易信任

当今社会&#xff0c;随着数字化和信息化的发展&#xff0c;电子合同已经成为商务活动中常见的签署方式。而在签署电子合同时进行实名认证&#xff0c;是为了确保合同的真实性、合法性和安全性。本文将从法律、技术和实际应用等方面详细解释为什么签署电子合同需要进行实名认证…...

c++ primer中文版第五版作业第十八章

仓库地址 文章目录 18.118.218.318.418.518.618.718.818.918.1018.1118.1218.1318.1418.1518.16位置一using声明 位置二using声明 位置一using指示 位置二using指示 18.1718.1818.1918.2018.2118.2218.2318.2418.2518.2618.2618.2818.2918.30 18.1 此时r是一个range_error类型…...

vue触发真实的点击 事件 跟用户行为一致

<template><div><button ref"myButton" click"handleClick">按钮</button></div> </template><script> export default {methods: {handleClick() {const button this.$refs.myButton;// 创建一个鼠标点击事件…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...