Offer必备算法06_位运算_十道力扣OJ题详解_由易到难

news2025/4/20 8:16:59

目录

位运算算法原理

①力扣191. 位1的个数

解析代码

②力扣338. 比特位计数

解析代码

③力扣461. 汉明距离

解析代码

④力扣136. 只出现一次的数字

解析代码

⑤力扣260. 只出现一次的数字 III

解析代码

⑥力扣面试题 01.01. 判定字符是否唯一

解析代码

⑦力扣268. 丢失的数字

解析代码

⑧力扣371. 两整数之和

解析代码

⑨力扣137. 只出现一次的数字 II

解析代码

⑩力扣面试题 17.19. 消失的两个数字

解析代码

本篇完。


位运算算法原理

常见位运算解题方法:

1. 基础位运算:

&:按位与,有0就是0

| :按位或,有1就是1

^ :按位异或,相同为0,相异为1/无进位相加

2. 给一个数 n,确定它的二进制表示中的第 x 位是 0 还是 1:

(n>>x)& 1 (n右移x位,按位与1)

为0则第x位为0,为1则第x位为1

3. 将一个数 n 的二进制表示的第 x 位修改成 1:

n l=(1<<x)   (n或等 1左移x位)

4. 将一个数 n 的二进制表示的第 x 位修改成 0:

n&=(~(1<<x))    (n与等 1左移x位然后按位取反)

5. 提取一个数 n 二进制表示中最右侧的1:

n &-n(将最右侧的 1,左边的区域全部变成相反)

6. 干掉一个数 n 二进制表示中最右侧的 1(循环此方法知道n为0即可计算n二进制1的数目)

n & (n-1)   (将最右侧的1,右边的区域(包含1)全部变成相反)

7. 异或(^)运算的运算律(解决只出现一次的数字(单身狗)问题)
a ^ 0 = a
a ^ a = 0
a ^ b ^ c = a ^ ( b ^ c)


①力扣191. 位1的个数

191. 位1的个数

难度 简单

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量)。

提示:

  • 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
  • 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 3 中,输入表示有符号整数 -3

示例 1:

输入:n = 00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

示例 2:

输入:n = 00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。

示例 3:

输入:n = 11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。

提示:

  • 输入必须是长度为 32 的 二进制串

进阶

  • 如果多次调用这个函数,你将如何优化你的算法?
class Solution {
public:
    int hammingWeight(uint32_t n) {

    }
};

解析代码

干掉最右边的1,然后计数器+1:

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int cnt = 0;
        while(n)
        {
            n &= (n - 1);
            ++cnt;
        }
        return cnt;
    }
};

②力扣338. 比特位计数

338. 比特位计数

难度 简单

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

示例 1:

输入:n = 2
输出:[0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10

示例 2:

输入:n = 5
输出:[0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

提示:

  • 0 <= n <= 10^5
class Solution {
public:
    vector<int> countBits(int n) {

    }
};

解析代码

只是(力扣191. 位1的个数)加了个循环:

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> v(n+1, 0);
        for(int i = 1; i <= n; ++i)
        {
            int cnt = 0, tmp = i;
            while(tmp)
            {
                tmp &= (tmp - 1);
                ++cnt;
            }
            v[i] = cnt;
        }
        return v;
    }
};

③力扣461. 汉明距离

461. 汉明距离

难度 简单

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

给你两个整数 x 和 y,计算并返回它们之间的汉明距离。

示例 1:

输入:x = 1, y = 4
输出:2
解释:
1   (0 0 0 1)
4   (0 1 0 0)
       ↑   ↑
上面的箭头指出了对应二进制位不同的位置。

示例 2:

输入:x = 3, y = 1
输出:1

提示:

  • 0 <= x, y <= 2^31 - 1
class Solution {
public:
    int hammingDistance(int x, int y) {

    }
};

解析代码

把两个数异或起来,计算其结果二进制1的数目:

class Solution {
public:
    int hammingDistance(int x, int y) {
        // return __builtin_popcount(x ^ y);
        int tmp = x ^ y, cnt = 0; // 不同则为1
        while (tmp) 
        {
            tmp &= (tmp - 1);
            ++cnt; // 依次左移到最低位
        }
        return cnt;
    }
};

④力扣136. 只出现一次的数字

136. 只出现一次的数字

难度 简单

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 1 :

输入:nums = [2,2,1]
输出:1

示例 2 :

输入:nums = [4,1,2,1,2]
输出:4

示例 3 :

输入:nums = [1]
输出:1

提示:

  • 1 <= nums.length <= 3 * 10^4
  • -3 * 10^4 <= nums[i] <= 3 * 10^4
  • 除了某个元素只出现一次以外,其余每个元素均出现两次。
class Solution {
public:
    int singleNumber(vector<int>& nums) {

    }
};

解析代码

之前写过了,以前讲异或讲过的单身狗:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int val = 0;
        for(const auto& e : nums)
        {
            val ^= e;
        }
        return val;
    }
};

⑤力扣260. 只出现一次的数字 III

260. 只出现一次的数字 III

难度 中等

给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

示例 1:

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。

示例 2:

输入:nums = [-1,0]
输出:[-1,0]

示例 3:

输入:nums = [0,1]
输出:[1,0]

提示:

  • 2 <= nums.length <= 3 * 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
  • 除两个只出现一次的整数外,nums 中的其他数字都出现两次
class Solution {
public:
	vector<int> singleNumber(vector<int>& nums) {

	}
};

解析代码

这也可以用排序,但这是以前写过的找两个单身狗的题:时间复杂度为O(N)

        如果我们按照只出现一次的数字的思路直接异或 肯定只会出来一个四不像数,假设数组1 2 3 3 1 4,我们把 两个单身狗分成两个组。而组中其他的数字就都不是单身狗。

        此时我们在分组异或就分别得到了2个单身狗,问题是以什么为依据分组?依据 二进制位 异或把相同的数字变成0,不同的数字变成1,根据1在哪位 就说明单身狗这个的二进制位不同 ,按照这个二进制位分(这就是那个四不像的数)两个单身狗是不可能进到一组的。

        ① 我们依然把数组中所有数字异或到一起 然后判断这个数字的二进制位 比如有两个单身狗2和40010 和0100最后异或完毕得到的二进制位是 0110 说明两个单身狗数字的二进制最后位是相等我们左移一(cnt)位得到了1 就说明 两个单身狗数字的倒数第二位二进制数 不相等

        ② 让数组中所有的数字左移一(cnt)位 如果等于 1 放进第一个数组中。如果等于0 放进第二个数组中。

        ③ 把数组中的数字全部异或就得到了 2个单身狗

class Solution {
public:
	vector<int> singleNumber(vector<int>& nums) {
		int sum = 0;
		for (const auto& e : nums)
		{
			sum ^= e;
		}
		int cnt = 0;
		for (int i = 0;i < 32;++i)
		{
			if (sum & (1 << i))// 第几位是1结果就是1
			{
				cnt = i;// 记录下来
			}
		}
		vector<int> v = { 0,0 };// C++11的初始化,类似数组
		for (const auto& e : nums)
		{
			if (e & (1 << cnt))
			{
				v[0] ^= e;
			}
			else
			{
				v[1] ^= e;
			}
		}
		return v;
	}
};

⑥力扣面试题 01.01. 判定字符是否唯一

面试题 01.01. 判定字符是否唯一

难度 简单

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false 

示例 2:

输入: s = "abc"
输出: true

限制:

  • 0 <= len(s) <= 100
  • s[i]仅包含小写字母
  • 如果你不使用额外的数据结构,会很加分。
class Solution {
public:
    bool isUnique(string astr) {

    }
};

解析代码

class Solution {
public:
    bool isUnique(string astr) {
        if(astr.size() > 26) // 鸽巢原理优化
            return false;
        
        int bits = 0;
        for(auto& e : astr)
        {
            int i = e - 'a';
            if((bits >> i) & 1)
            {
                return false;
            }
            bits |= (1 << i);
        }
        return true;
    }
};

⑦力扣268. 丢失的数字

268. 丢失的数字

难度 简单

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例 1:

输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 2:

输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 3:

输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。

示例 4:

输入:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。

提示:

  • n == nums.length
  • 1 <= n <= 10^4
  • 0 <= nums[i] <= n
  • nums 中的所有数字都 独一无二
class Solution {
public:
    int missingNumber(vector<int>& nums) {

    }
};

解析代码

转化成找一个单身狗(力扣136):

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int ret = 0;
        for(auto& e: nums)
        {
            ret ^= e;
        }
        for(int i = 0; i <= nums.size(); ++i)
        {
            ret ^= i;
        }
        return ret;
    }
};

⑧力扣371. 两整数之和

371. 两整数之和

难度 简单

给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。

示例 1:

输入:a = 1, b = 2
输出:3

示例 2:

输入:a = 2, b = 3
输出:5

提示:

  • -1000 <= a, b <= 1000
class Solution {
public:
    int getSum(int a, int b) {

    }
};

解析代码

        此题知识点就是异或运算为无进位相加,异或后想办法找到进位就行了,进位就是两个数按位与然后左移一位,重复相加至进位为0即为答案。

class Solution {
public:
    int getSum(int a, int b) {
        while (b != 0)
        {
            unsigned int carry = (unsigned int)(a & b) << 1; // 进位
            a = a ^ b; // 无进位相加
            b = carry; // 进位不为0的话就一直加,如a已经是a^b的结果,再^b,加进位
        }
        return a;
    }
};

⑨力扣137. 只出现一次的数字 II

137. 只出现一次的数字 II

难度 中等

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

示例 1:

输入:nums = [2,2,3,2]
输出:3

示例 2:

输入:nums = [0,1,0,1,0,1,99]
输出:99

提示:

  • 1 <= nums.length <= 3 * 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
  • nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
class Solution {
public:
    int singleNumber(vector<int>& nums) {

    }
};

解析代码

1. 基础位运算:

&:按位与,有0就是0

| :按位或,有1就是1

^ :按位异或,相同为0,相异为1/无进位相加

        之前用暴力和sort写过了,现在再用位运算写一下,思路就是把全部数的二进制位加起来,模3(一个数出现一次,其它出现n次就是模n),因为如果不看只出现一次的数,其它二进制位加起来不是3n个0就是3n个1,那一位全加起来模3的话剩的就是只出现一次的数的二进制位。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for(int i = 0; i < 32; ++i) // 依次修改ret的32个比特位->0改1
        {
            int sum = 0;
            for(auto e : nums)
            {
                // if(((e >> i) & 1) == 1)
                // {
                //     ++sum; // 依次统计所有数的第i位二进制位
                // }
                sum += ((e >> i) & 1); // 即上面注释掉的代码简化,不是加0就是加1
            }
            if(sum %= 3) // 说明这是只出现一次的数剩的1
            {
                ret |= (1 << i); // ret第i位改为1
            }
        }
        return ret;
    }
};

⑩力扣面试题 17.19. 消失的两个数字

面试题 17.19. 消失的两个数字

难度 困难

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

以任意顺序返回这两个数字均可。

示例 1:

输入: [1]
输出: [2,3]

示例 2:

输入: [2,3]
输出: [1,4]

提示:

  • nums.length <= 30000

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {

    }
};

解析代码

        困难题,但之前写过找一个单身狗和找两个单身狗的了,转化成找两个单身狗(力扣260),再转化成找一个单身狗(力扣136)(力扣268):

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        int sum = 0, n = nums.size();
        for(int i = 1; i <= n + 2; ++i)
        {
            nums.push_back(i); // 转换成找两个单身狗->力扣260
        }
        n = nums.size();
        for (int i = 0; i < n; i++)
        {
            sum ^= nums[i];
        }
        int count = 0;
        for (int i = 0; i < 32; i++)
        {
            if (sum & 1 << i) //循环判断第几位是1
            {
                count = i;//如果是1 记录下来
                break;
            }
        }
        int a = 0, b = 0;
        for (int i = 0; i < n; i++)
        {
            if (nums[i] & 1 << count)
                a ^= nums[i];
            else
                b ^= nums[i];
        }
        return {a, b};
    }
};

本篇完。

下一部分是关于递归的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1447028.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

day 20(补2.5)

fread 函数&#xff1a; 今日练习 C语言面试题5道~ 1. static 有什么用途&#xff1f;&#xff08;请至少说明两种&#xff09; 1) 限制变量的作用域 2) 设置变量的存储域 2. 引用与指针有什么区别&#xff1f; 1) 引用必须被初始化&#xff0c;指针不必。 2) 引用初始…

MYSQL学习笔记:MYSQL存储引擎

MYSQL学习笔记&#xff1a;MYSQL存储引擎 MYSQL是插件式的存储引擎 存储引擎影响数据的存储方式 存储引擎是用来干什么的&#xff0c;innodb和myisam的主要区别–数据存储方式----索引 mysql> show engines; ----------------------------------------------------------…

目标识别,跟踪模块

Tofu5m 是高性价比目标识别跟踪模块&#xff0c;支持可见光视频或红外网络视频的输入&#xff0c;支持视频下的多类型物体检测、识别、跟踪等功能。 产品支持视频编码、设备管理、目标检测、深度学习识别、跟踪等功能&#xff0c;提供多机版与触控版管理软件&#xff0c;为二次…

VLAN间通信

VLAN间通信的三种方法 vlanif接口 最常用&#xff0c;又叫虚拟接口&#xff0c;这种方式一般使用三层交换机实现&#xff0c;它包含路由模块和交换模块&#xff0c;交换模块可以实现剥离和添加VLAN标签,路由模块实现路由功能 VLANif接口 为各自vlan的网关 # interface Vlani…

常见范数介绍

一、在线性代数中&#xff0c;符号 ( ||x|| ) 表示向量 ( x ) 的范数&#xff08;Norm&#xff09;。范数是一个将向量映射到非负值的函数&#xff0c;它衡量了向量的大小或长度。范数可以是多种类型&#xff0c;其中最常见的有&#xff1a; 欧几里得范数&#xff08;L2范数&am…

8868体育助力西甲皇家马德里足球俱乐部 皇马占据争冠优势

西甲的皇家马德里足球俱乐部是8868体育合作的俱乐部之一&#xff0c;这支拥有悠久历史和辉煌成就的豪门球队&#xff0c;本赛季再次展现了它的强大实力。18胜4平1负&#xff0c;暂居榜首&#xff0c;这样的成绩足以让任何对手望而却步。然而&#xff0c;足球场上的对决永远充满…

《Linux 简易速速上手小册》第7章: 网络配置与管理(2024 最新版)

文章目录 7.1 Linux 网络基础7.1.1 重点基础知识7.1.2 重点案例&#xff1a;配置静态 IP 地址7.1.3 拓展案例 1&#xff1a;使用 nmcli 配置网络&#xff08;适用于 Fedora/CentOS&#xff09;7.1.4 拓展案例 2&#xff1a;配置无线网络连接 7.2 静态与动态 IP 配置7.2.1 重点基…

使用Docker快速部署MySQL

部署MySQL 使用Docker安装&#xff0c;仅仅需要一步即可&#xff0c;在命令行输入下面的命令 docker run -d \--name mysql \-p 3306:3306 \-e TZAsia/Shanghai \-e MYSQL_ROOT_PASSWORD123456 \mysql MySQL安装完毕&#xff01;通过任意客户端工具即可连接到MySQL. 当我们执…

【JVM篇】什么是双亲委派机制

文章目录 &#x1f354;什么是双亲委派机制⭐案例 &#x1f339;双亲委派机制有什么用 &#x1f354;什么是双亲委派机制 指的是&#xff1a;当一个类加载器接收到加载类的任务的时候&#xff0c;会向上查找是否加载过&#xff0c;再从上到下进行加载 &#xff08;因为要上下查…

Java实现软件学院思政案例库系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理员2.2 普通教师 三、系统展示四、核心代码4.1 查询思政案例4.2 审核思政案例4.3 查询思政课程4.4 思政案例点赞4.5 新增思政案例评语 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的软件学…

Excel一键导入导出-EasyPOI

EasyPOI是一款优秀的开源Java库&#xff0c;专为简化和优化Excel文件的导入导出操作而设计。下面&#xff0c;我会介绍EasyPOI在项目中使用EasyPOI&#xff0c;实现Excel文件的高效操作。帮助读者全面了解和掌握这一工具。 EasyPOI简介 官网&#xff1a; http://www.wupaas.co…

python 基础知识点(蓝桥杯python科目个人复习计划39)

今日复习内容&#xff1a;排序 昨天晚上快睡的时候&#xff0c;脑子里就突然想到了排序&#xff0c;所以就打算再复习一遍相关知识点。 我先说一下冒泡排序&#xff0c;冒泡排序其实很好理解&#xff0c;比如有n个人排队&#xff08;从矮到高&#xff09;&#xff0c;先从这n…

Codeforces Round 923 (Div. 3) C. Choose the Different Ones(Java)

比赛链接&#xff1a;Round 923 (Div. 3) C题传送门&#xff1a;C. Choose the Different Ones! 题目&#xff1a; ** Example** ** input** 6 6 5 6 2 3 8 5 6 5 1 3 4 10 5 6 5 6 2 3 4 5 6 5 1 3 8 10 3 3 3 4 1 3 5 2 4 6 2 5 4 1 4 7 3 4 4 2 1 4 2 2 6 4 4 2 1 5 2 3 …

强大的头像制作神器微信小程序源码/支持外卖CPS等优惠劵小程序源码

强大的头像制作神器微信小程序源码&#xff0c;支持外卖CPS等优惠劵小程序源码&#xff1b;这是一款目前见到比较丰富的头像制作小程序&#xff0c;拥有丰富的模板&#xff0c;多种分类基本大全。 支持直接获取微信头像&#xff0c;或者直接上传图片&#xff1b;另外上传的话还…

代码控制邮件服务器发送电子邮件

1、引言 在用户注册的时候我们如果需要让用户接收动态验证码通常有两种方式。一种是给用户发送短信验证码&#xff0c;另一种是发送邮箱验证码。而发送短信验证码的话就必须购买短信流量&#xff0c;这无疑增加了投入的成本&#xff0c;那么此时我们可以使用发送邮箱验证码的形…

Vision Transformer Pytorch 实现代码学习记录

目前运营的社交平台账号&#xff1a; CSDN 【雪天鱼】: 雪天鱼-CSDN博客哔哩哔哩 【雪天鱼】: 雪天鱼个人主页-bilibili.com 可能后续有更新&#xff0c;也可能没有更新&#xff0c;谨慎参考 V1.0 24-02-13 ViT 代码的基本训练, 预测推理脚本运行 1 学习目标 能用官方的 ViT…

渗透测试练习题解析 3(CTF web)

1、[网鼎杯 2020 朱雀组]phpweb 1 考点&#xff1a;反序列化漏洞利用 进入靶场&#xff0c;查看检查信息&#xff0c;发现存在两个参数 func 和 p 查看页面源代码 payload&#xff1a;funcfile_get_contents&pphp://filter/resourceindex.php 整理后&#xff0c;就是 PHP 代…

操作系统——1.3 操作系统运行环境

1.3 操作系统运行环境 一、概念 操作系统运行机制总览 应用程序与内核程序 特权指令与非特权指令 内核态与用户态 CPU在内核态与用户态的切换 操作系统运行机制的总结 中断和异常总览 中断的作用 中断的类型 内中断的例子 外中断的例子 中断的分类&am…

腾讯云4核8G服务器多少钱?轻量和CVM报价2024新版

腾讯云4核8G服务器S5和轻量应用服务器优惠价格表&#xff0c;轻量应用服务器和CVM云服务器均有活动&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;标准型SA2服务器1444.8元一年&#xff0c;轻量应用服务器4核8G12M带宽一…

漫漫数学之旅018

文章目录 经典格言数学习题古今评注名人小传 - 库尔特哥德尔 经典格言 一个毫无自由的社会——一个人凡事都要遵循严格统一的规则——将在行为上既不一致也不完全&#xff0c;甚至不能解决某些也许很重要的问题。——库尔特哥德尔&#xff08;Kurt Gdel&#xff09; 库尔特哥德…