简述

在知乎上看到一个题目,解答很有意思,用的是位运算。
这让我觉得位运算有更多的算法可能,但是却还没被我用过。
这种东西都是第一次看,觉得挺牛的,第二次,第三次看的时候就觉得没什么了。So,大佬们轻喷。

基础

涉及到二进制运算,如下:

  • & | ^ 三种运算,分别对应着交,并,异或

    • 交:两个对应位都是1,则为1,否则为0
    • 并:两个对应位只有一个是1,则为1,否则为0
    • 异或:两个对应位相同则为0,不同则为1
  • >> 往右移动,箭头相反则为往左移动

这就是所有二进制的运算了。但就是由这里的这些推导出了很多有趣的运算范式。这些范式也可以称之为基础。

  • A为任何数,

    • 0 & A = 0
    • 0 | A = 0
    • 0 ^ A = A
    • A ^ A = 0

第三条需要解释下:二进制只有0或者1。0的二进制任何位置都是0。A的数,任何一个位置。如果是1,则1和0不同,该位置还是1。如果该位置为0,则0和0相同,该位置还是0。故不变

  • 明显,三则运算满足交换律和结合律。

这个验证简单,画个表就知道了。只需要考虑任取一个位置,画对应的表就好了。

  • 交换:A,B两个数交换

    • A = A ^ B
    • B = A ^ B
    • A = A ^ B
    • 就完成交换了。

这种交换方式也是非常基础的acm东西。如果解释也是非常简单的。(注意,下面的表达式中, 每个表达式的第一个均为赋值的意思,后面的等号就是相等的意思)

  • 第一步:A = A ^ B
  • 第二步实际上为:B = (A ^ B) ^ B,再由交换律和结合律,变为 B = A ^ (B ^ B) = A ^ 0 = 0 ^ A = A
  • 第三步实际上为:A = (A ^ B) ^ A, (原来这里的B已经是实际上的A了),同样的, A = B。

扩展应用

数字去重

这个就是我之前说的,看到了那篇文章:https://www.zhihu.com/question/33776070/answer/703697146?utm_source=wechat_session&utm_medium=social&utm_oi=806197504654839808

这里说的去重,是

  • 把重复两次(或者是偶数次)的那些数字给去掉。
  • 而且数据集中只能有一个只出现一次的数字。

(应该是个相当naive的问题了)

这种问题,由于约束比default的版本更多,所以说,才可以用上这个答主给的那个版本的代码。

例如:

  • 数据集为 1 2 3 4 5 1 2 3 4, 那么我们要找到这个5
  • 其他实例为: 1 2 3 1 2 要找到 3。这里只会有一个目标数字,且每个数字的重复都只有一次。
    • 1 2 1 2 1 2 3 这样的数据就不行了。
    • 1 2 3 1 2 4 这样的数据集,就需要改进了。这个改进回答也有,但我嫌弃他解释的太麻烦。

方法: 异或

1^2^3^4^5^1^2^3^4 = (1^1)^(2^2)^(3^3)^(4^4)^5 = 0 ^ 5 = 5

#include <iostream>
using namespace std;int main() {int a[] = { 1,2,3,4,5,1,2,3,4};int tmp = a[0];for (int i = 1; i < 9; ++i)tmp ^= a[i];cout << tmp << endl;system("pause");
}

去重改进

如上所说,可以改进到

  • 把重复两次(或者是偶数次)的那些数字给去掉。
  • 而且数据集中只能有两个只出现一次的数字。(且只能有两个)

标准数据是:1 2 3 1 2 4

  • 回忆下上一个:

    • 其实我们这得到的就是第一步得到的 A ^ B
    • 那想把A或者B提取出来。按照知乎那哥们那么说也是可以的。但是真的是麻烦
    • 简单点: A ^ (A ^ B) = B。且异或运算也是唯一性的。给一个数组,设置为空。
      • 遍历:拿到第i个数,是否已经在上面新建的数组中了,在则这个数就是我们想要的,否者,将 这个数和A^B做异或的数值存下来。

如下:

  • 注意到:这个时间复杂度是n2n^2n2的。(知乎上那个也是n2n^2n2),但他那个不好降低。

    • 优化,通过哈希的方式来降低时间复杂度。也可以使用平衡二叉树。或者是平衡二叉树和哈希的结合。
    • 平衡二叉树的,插入,删除,查找都是log(n)log(n)log(n)的。因此也不复杂度就被降到了O(nlogn)
#include <iostream>
using namespace std;int main() {int a[] = { 1,2,3,1,2,4 };int b[] = { 0,0,0,0,0,0 };int tmp = a[0], i, j;for (i = 1; i < 7; ++i)tmp ^= a[i];for (i = 0; i < 7; ++i) {for (j = 0; j < i; ++j) { if (b[j] == a[i]) { cout << a[i] << " " << (tmp ^ a[i]) << endl;  break; } }if (j != i) break;b[i] = tmp ^ a[i];}system("pause");
}

如果以后想到再继续补充吧

c语言或者cpp中位运算的技巧相关推荐

  1. c语言中位运算之布尔运算

    c语言中位运算中的布尔运算有:&.|.~.^ &:按位与 |:按位或 ~:按位非 ^:按位异或,相同为0,相异为1. 计算规则如下: 位的逻辑运算的作用: 使用位向量做集合编码: 使用 ...

  2. c语言用位运算将一个数清零,C语言学习笔记_位运算

    C语言学习笔记_位运算 知识点记录 基本位运算 按位与:全1为1,见0为0:与1相与无变化,与0相与变为0:可用于特定位清零 按位或:见1为1,全0为0:与1相或变为1,与0相或无变化:可用于特定位置 ...

  3. c语言位运算试题及解析,C语言面试题分类-位运算

    1.不用临时变量交换两个整数. a = a ^ b; b = a ^ b; a = a ^ b; 2.实现一个函数,输入一个整数,输出该数二进制表示中1的个数.例如9的二进制是1001,则输出2. i ...

  4. C/C++中位运算操作符的使用

    C/C++中位运算操作符的使用 介绍 使用 "与"运算符 "或"运算符 "取反操作" "异或"运算符 "左移& ...

  5. 算法之美 | 位运算的巧妙奥秘(一) | JAVA中位运算的深入浅出

    文章目录 前言 一.位运算符号 二.位运算的运算规则 扩展 前言 传智杯初赛后有感而写,我目前阶段所学习的算法,只是最基础的数学,对于数字和数学公式还是不敏感,在小卡与质数2那道题,解题的思路只有最基 ...

  6. 从labuladong东哥那里看到的位运算小技巧

    从labuladong东哥那里看到的位运算小技巧 1. 利用或操作 `|` 和`空格`将英文字符转换为小写 2. 利用与操作 `&` 和`下划线`将英文字符转换为大写 3. 利用异或操作 `^ ...

  7. c语言位运算负数的实例_一招教你学会C语言中位运算

    程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算说穿了,就是直接对整数在内存中的二进制位进行操作.注意,位运算只针对于整数进行操作. 运算符号 运算规则 1.&与运算:对应两个二进 ...

  8. C语言截取整数的某些位编程,C语言中位运算的巧用(转)

    一 .位运算实例 1.用一个表达式,判断一个数X是否是2的N次方(2,4,8,16.....),不可用循环语句. X:2,4,8,16转化成二进制是10,100,1000,10000.如果减1则变成0 ...

  9. C语言中位运算异或“∧”的作用

    前言: 为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长. 1.概念 异或运算符"∧"也称XOR运算符.它的规则是 ...

最新文章

  1. 入门Promise的正确姿势
  2. linux Makefile中 make -C和M=的作用
  3. kinect 录制彩色和深度视频
  4. 使用Java EE安全性和JBoss AS 7.x保护JSF应用程序的安全
  5. 文档中快速输入日期时间的方法
  6. 25q64存储多个数据_一篇文章看懂,存储虚拟化在不同用例中的实践与优势
  7. 国科大高级人工智能10-强化学习(多臂赌博机、贝尔曼)
  8. java监听数据库操作_第十六篇——JDBC操作数据库之监听器
  9. Android4.0的Alertdialog对话框,设置点击其他位置不消失
  10. 信息学奥赛一本通C++语言——1040:输出绝对值
  11. Java关键字表格、Java有哪些关键字?
  12. Windows10下python pip卸载并重新安装
  13. 网易云课堂 python网络爬虫实战
  14. GIS系列专题(3):缓冲区算法对比研究(Buffer Algorithm),类似刀具补偿
  15. 【下载】《美语语音训练》American Accent Training 文本+MP3
  16. 多平台专业的 OCR 图文精准识别工具!便宜又好用! - 极度扫描
  17. MATLAB等高线图
  18. 什么是restful?说说你对restful的理解
  19. 2038计算机系统,2038年问题
  20. 淘宝运营,什么是千人千面,什么是人群标签,如何通过千人千面,实现转化率翻倍

热门文章

  1. 在SD/MMC卡上实现hive (Implement WinCE HIVEROM system on NAND or SD system )
  2. 如何搭建modem编译环境
  3. 你以为 CSS 只是个简单的布局?装逼指南了解一下
  4. Win32_16来看看标准菜单和右键菜单的玩法
  5. FFmpeg 源码学习(一):avformat_open_input 源码分析
  6. Linux阶段总结shell脚本
  7. Docker实战第二天(Docker常用命令详解)
  8. HDU1266 Reverse Number
  9. 服务器系统换系统,服务器更换系统
  10. java求面积Shape类_Shape-2,形状类,正方形类,长方形类,圆类,求周长面积