IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++算法之神奇的位运算 -> 正文阅读

[C++知识库]C++算法之神奇的位运算

位运算

位运算是算法题里比较特殊的一种类型,它们利用二进制位运算的特性进行一些奇妙的优化
和计算。常用的位运算符号包括:“∧”按位异或、“&”按位与、“|”按位或、“~”取反、“<<”
算术左移和“>>”算术右移。以下是一些常见的位运算特性,其中 0s 和 1s 分别表示只由 0 或 1
构成的二进制数字。
在这里插入图片描述

1.基础问题

给定两个十进制数字,求它们二进制表示的汉明距离(Hamming distance,即不同位的个数)。
在这里插入图片描述
题解:对两个数进行按位异或操作,统计有多少个1即可。

int hanmingDistance(int x,int y)
{
    int diff=x ^ y,ans=0;
    while(diff)
    {
        ans+=diff&1;
        diff>>=1;
    }
    return ans;
}

题目一:
给定一个十进制整数,输出它在二进制下的翻转结果
在这里插入图片描述
题解:使用算数左移和右移,可以轻易的实现二进制的翻转

uint32_t reverseBits(unit32_t n)
{
    unit32_t ans=0;
    for(int i=0;i<32;++i)
    {
        ans <<= 1;
        ans += n & 1;
        n >>= 1;
    }
    return ans;
}       

题目二:
给定一个整数数组,这个数组里只有一个数次出现了一次,其余数字出现了两次,求这个只出现一次的数字。
在这里插入图片描述
我们可以利用 x ∧ x = 0 和 x ∧ 0 = x 的特点,将数组内所有的数字进行按位异或。出现两次的所有数字按位异或的结果是 0,0 与出现一次的数字异或可以得到这个数字本身。

int singleNumber(vector<int>& nums)
{
    int ans=0;
    for(const int & num:nums)
    {
        ans ^= num;
    }
    return ans;
}

2.二进制特性

利用二进制的一些特性,我们可以把位运算使用到更多问题上。
例如,我们可以利用二进制和位运算输出一个数组的所有子集。假设我们有一个长度为 n 的
数组,我们可以生成长度为 n 的所有二进制,1 表示选取该数字,0 表示不选取。这样我们就获
得了 2n 个子集。
题目一:
给定一个整数,判断它是否是 4 的次方。
在这里插入图片描述
首先我们考虑一个数字是不是 2 的(整数)次方:如果一个数字 n 是 2 的整数次方,那么它的二进制一定是 0…010…0 这样的形式;考虑到 n ? 1 的二进制是 0…001…1,这两个数求按位与的结果一定是 0。因此如果 n & (n - 1) 为 0,那么这个数是 2 的次方。如果这个数也是 4 的次方,那二进制表示中 1 的位置必须为奇数位。我们可以把 n 和二进制的 10101…101(即十进制下的 1431655765)做按位与,如果结果不为 0,那么说明这个数是 4 的次方。

bool isPowerOfFour(int n)
{
    return n > 0 && !(n & (n-1)) && (n & 1431655765);
}

题目二:
给定多个字母串,求其中任意两个字母串的长度乘积的最大值,且这两个字母串不能含有相同字母。
在这里插入图片描述
怎样快速判断两个字母串是否含有重复数字呢?可以为每个字母串建立一个长度为 26 的二进制数字,
每个位置表示是否存在该字母。如果两个字母串含有重复数字,那它们的二进制表示的按位与不为 0。同时,我们可以建立一个哈希表来存储字母串(在数组的位置)到二进制数字的映射关系,方便查找
调用。

int maxProduct(vector<string>& words)
{
    unordered_map<int,int>hash;
    int ans=0;
    for(const string & word : words)
    {
        int mask=0,size=word.size();
        for(const char & c : word)
        {
            mask |= 1 << (c - 'a');
        }
        hash[mask] = max(hash[mask],size);
        for(const auto& [h_mask,h_len]:hash)
        {
            if(!(mask & h_mask))
            {
                ans = max(ans,size * h_len);
            }
        }
    }
    return ans;
}

题目三:
给定一个非负整数 n,求从 0 到 n 的所有数字的二进制表达中,分别有多少个 1。

    输入是一个非负整数 n,输出是长度为 n + 1 的非负整数数组,每个位置 m 表示 m 的二进制里有多少个 1。

在这里插入图片描述
本题可以利用动态规划和位运算进行快速的求解。定义一个数组 dp,其中 dp[i] 表示数字 i的二进制含有 1 的个数。对于第 i 个数字,如果它二进制的最后一位为 1,那么它含有 1 的个数则为 dp[i-1] + 1;如果它二进制的最后一位为 0,那么它含有 1 的个数和其算术右移结果相同,即dp[i>>1]。

vector<int>countBits(int num)
{
    vector<int>dp(num+1,0);
    for(int i=1;i<=num;++i)
    {
        dp[i] = i & 1 ? dp[i-1] + 1: dp[i>>1];
        //等价于dp[i] = dp[i&(i-1)] + 1;   
    }
    return dp;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-14 13:08:38  更:2021-09-14 13:10:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 21:04:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码