【C++刷题】优选算法——位运算

2024-06-01 06:36
文章标签 算法 c++ 运算 刷题 优选

本文主要是介绍【C++刷题】优选算法——位运算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

常见位运算操作总结:

  1. 基础位运算
    &:有0则为0
    |:有1则为1
    ^:相同为0,相异为1 / 无进位相加
  2. 运算符的优先级
    管它什么优先级,加括号就完事儿了
  3. 给一个数 n,确定它的二进制表示中的第 i (默认是从右起第0位) 位是 0 还是 1
    (n >> i) & 1
  4. 将一个数 n 的二进制表示的第 i 位修改为 1
    n |= (1 << i)
  5. 将一个数 n 的二进制表示的第 i 位修改成 0
    n &= (~(1 << i))
  6. 提取一个数 n 二进制表示中最右侧的 1 (lowbit操作)
    n & (-n)
    (-n) 将 n 最右侧的 1 的 左边的区域 全部变成了相反的位
  7. 干掉一个数 n 二进制表示中最右侧的 1
    n &= (n - 1)
    (n - 1) 将 n 最右侧的 1 的 右边的区域(包括最右侧的1),全部变成了相反的位
  8. 异或 ^ 运算的运算律
    n ^ 0 = n
    n ^ n = 0 - 消消乐
    a ^ b ^ c = a ^ (b ^ c)

根据第6、7条位运算操作,可以搞定1-3题。

  1. 位1的个数
int hammingWeight(int n)
{int ret = 0;while(n){++ret;n &= (n - 1);}return ret;
}
  1. 比特位计数
int hammingWeight(int n)
{int ret = 0;while(n){++ret;n &= (n - 1);}return ret;
}
vector<int> countBits(int n)
{vector<int> ret(n + 1);for(int i = 1; i <= n; ++i){ret[i] = hammingWeight(i);}return ret;
}
  1. 汉明距离
int hammingWeight(int n)
{int ret = 0;while(n){++ret;n &= (n - 1);}return ret;
}
int hammingDistance(int x, int y)
{int ret = 0;while(x && y){if((x & (-x)) < (y & (-y))){++ret;x &= (x - 1);}else if((x & (-x)) > (y & (-y))){++ret;y &= (y - 1);}else{x &= (x - 1);y &= (y - 1);}}ret += hammingWeight(x);ret += hammingWeight(y);return ret;
}

结合第 8 条位运算操作,可以搞定4-5题。
4. 只出现一次的数字

int singleNumber(vector<int>& nums)
{int ret = 0;for(int e : nums) ret ^= e;return ret;
}
  1. 只出现一次的数字 III
vector<int> singleNumber(vector<int>& nums)
{long long lowbit = 0;for(int e : nums) lowbit ^= e;lowbit &= (-lowbit);long long low_0 = 0, low_1 = 0;for(int e : nums){if(e & lowbit) low_1 ^= e;else low_0 ^= e;}return {(int)low_0, (int)low_1};
}
  1. 判定字符是否唯一
bool isUnique(string astr) 
{if(astr.size() > 26) return false;int hash = 0;for(char c : astr){int bit = 1 << (c - 'a');if( hash & bit ) return false;else hash |= bit;}return true;
}
  1. 丢失的数字
// 高斯求和
int missingNumber(vector<int>& nums)
{int n = nums.size();int sum = (0 + n) * (n + 1) / 2;for(int e : nums) sum -= e;return sum;
}// 异或 运算律
int missingNumber(vector<int>& nums)
{int n = nums.size();int ret = 0;for(int i = 0; i <= n; ++i) ret ^= i;for(int e : nums) ret ^= e;return ret;
}
  1. 两整数之和
int getSum(int a, int b)
{while(b){int no_carry = a ^ b;int carry = (a & b) << 1;a = no_carry;b = carry;}return a;
}
  1. 只出现一次的数字 II
int singleNumber(vector<int>& nums)
{int ret = 0;for(int i = 0; i < 32; ++i){int num = 0;for(int e : nums) if( e & (1 << i) ) ++num;if(num % 3) ret |= (1 << i);}return ret;
}
  1. 消失的两个数字
vector<int> missingTwo(vector<int>& nums)
{int n = nums.size();int N = n + 2;int num = 0;for(int i = 1; i <= N; ++i) num ^= i;for(int e : nums) num ^= e;int lowbit = num & (-num);int low_0 = 0, low_1 = 0;for(int i = 1; i <= N; ++i){if(i & lowbit) low_1 ^= i;else low_0 ^= i;}for(int e : nums){if(e & lowbit) low_1 ^= e;else low_0 ^= e;}return {low_0, low_1};
}

这篇关于【C++刷题】优选算法——位运算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1020247

相关文章

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数