leetCode-hot100-位运算专题

news2024/11/24 15:22:22

例题中的视频讲解是B站中的宝藏博主的讲解视频,每道题后面都附有该题对应的视频链接~

位运算知识总结

    • 1.异或
    • 2.与运算和或运算
    • 3.左移和右移
    • 4.综合例题

1.异或

参考资料:位运算-异或,以下知识点讲解的内容参考了该篇博文,有兴趣的伙伴可以去看看,讲的很详细。在知识点的后面加入了该知识点相关的例题,所有的例题都来自力扣-hot100,按照题号搜索题目即可。
概念
按位异或表示当两个二进制当前位相同则值为0,不同则为1
特点(重要!):
(1)0 异或 任何数 = 任何数(0^0=0,0^1=1
(2)1 异或 任何数 = 任何数取反 (1^0=1,1^1=0
(3)任何数 异或 自己 = 把自己置为0
常见用途
(1)实现特定位置的翻转
要将某个二进制数字的特定位置取反,可以让其与同位数的二进制数字异或,该二进制除了对应的特定位置为1,其他位置都为0(eg,将01011101的第2位和第3位取反,则可以与00000110异或)
(2)在不使用临时变量的情况下将两个数的值进行交换(a:10110110和b:00001101)

a = a ^ b
b = b ^ a
a = a ^ b

例题
136.只出现一次的数字
思路
本题用到了异或运算特点中(2)和(3):

  • 任何数异或自身等于把自己置为0 ->我们将数组中的所有元素异或,那么出现两次的元素全部变为0
  • 0异或任何数等于任何数 ->经过上个步骤的处理,数组中只有0和只出现一次的数字,异或后即可得到该元素。

视频讲解点击视频讲解-只出现一次的数字。
时间复杂度
时间复杂度为O(n)n为数组的长度。
代码实现

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for(int i = 0; i < nums.length;i++){
            ans = ans ^ nums[i];
        }
        return ans;
    }
}

268.丢失的数字
思路
本题和136题是相同的,将0~n的所有数字和数组元素异或,最后的结果即为结果,这里ans初始值设置为n,因为在循环中不包含n,数组的长度是n-1
时间复杂度
时间复杂度为O(n)n为数组的长度。
代码实现

class Solution {
    public int missingNumber(int[] nums) {
        int ans = nums.length;
        for(int i = 0; i < nums.length; i++){
            ans ^= nums[i] ^ i;
        }
        return ans;
    }
}

389.找不同
思路
本题的思路和268题类似,由于两个相同字符异或结果为 0,则 st 的全部字符异或之后就是 t 中添加的字符。其中由于 t 的长度比 s 大1,所以答案的初始值设置为 t 的最后一个字符。
时间复杂度
时间复杂度为O(n),其中n为字符串s的长度。
代码实现

class Solution {
    public char findTheDifference(String s, String t) {
        char c = t.charAt(t.length() - 1);
        for(int i = 0; i < s.length(); i++){
            c ^= s.charAt(i) ^ t.charAt(i);
        }
        return c;
    }
}

2.与运算和或运算

与运算和或运算比较简单,这里简单介绍一下
概念
与运算(&):两者都为1时结果为1,其余情况为0
或运算(|) :两者中有一个为1时结果为1,其余情况为0
使用场景
(1) n & (n - 1):用来判断一个数是否为2的幂,如果结果为0,则说明 n 是2的幂,否则不是,同时还可以统计一个数的二进制表示中有多少个1。
原理分析:
这个操作的原理是,对于一个2的幂,其二进制表示只有一个1,其余位都为0。而对于 n-1,其二进制表示中的最高位为0,其余位都为1。所以,当 nn-1 进行按位与操作时,如果结果为0,则说明 n 是2的幂,否则不是(eg. 8(1000) 和7(0111)按位与,结果为0,说明8的2
的幂)。
…待完善
例题
231.2的幂
思路
本题使用到的是使用场景中的(1)可以直接解决,需要注意的是0和负数不可能是2的幂,所以需要返回false
时间复杂度
时间复杂度为O(1),无论输入的n是多少,代码都只需要执行一次位运算操作即可判断n是否为2的幂次。
代码实现

class Solution {
    public boolean isPowerOfTwo(int n) {
        return n > 0 && (n & (n - 1)) == 0;
    }
}

3.左移和右移

概念
左移运算符m<<n表示吧m左移n位。左移n位的时候,最左边的n位将被丢弃,同时在最右边补上n个0。
右移运算符m>>n表示把m右移n位。右移n位的时候,最右边的n位将被丢弃。但右移时处理最左边位的情形要稍微复杂一点。这里要特别注意,如果数字是一个无符号数值,则用0填补最左边的n位。如果数字是一个有符号数值,则用数字的符号位填补最左边的n位。也就是说如果数字原先是一个正数,则右移之后再最左边补n个0;如果数字原先是负数,则右移之后在最左边补n个1。
使用场景
(1)获取x的第k位:(x >> k) & 1
(2)将1或0添加到x的最后一位 :(x << 1) | 1或0
例题
190.颠倒二进制位
思路
使用左移和右移运算使用场景的(1)和(2),使用(n >> k) & 1取到n的第k位置,使用(x << 1) | 1或0将取到的第k位依次添加到答案中,视频讲解点击视频讲解-颠倒二进制位。
时间复杂度
时间复杂度为O(1),即常数时间复杂度。无论输入的n是多少,代码都需要执行32次循环。
代码实现

public class Solution {
    // you need treat n as an unsigned value
    public int reverseBits(int n) {
        int ans = 0;
        for(int i = 0 ; i < 32; i++){
            ans = (ans << 1) | ((n >> i) & 1);
        }
        return ans;
    }
}

191.位1的个数
思路1
通过右移依次得到n的每一位,然后和1做与运算,如果为1则结果+1,反之+0,最后处理完n后即可得到结果值,视频讲解点击视频讲解-位1的个数。
时间复杂度
时间复杂度是O(1),因为循环次数固定为32次。
代码实现

class Solution {
    public int hammingWeight(int n) {
        int ans = 0;
        for(int i = 0; i < 32; i++){
            ans += (n >> i) & 1;
        }
        return ans;
    }
}

思路2
使用与运算中的使用场景中的第(1) n & (n - 1):统计一个数的二进制表示中有多少个1,每次执行 n & (n - 1)时都会消去n中的一位1,ans++,当n为0时及n中的1被全部消掉,此时ans即为所求。
时间复杂度
时间复杂度为O(logn),其中n表示给定的整数n的位数。代码中的while循环会执行的次数取决于n的二进制表示中1的个数,而一个整数n的二进制表示中1的个数最多为logn,因此时间复杂度为O(logn)
代码实现

class Solution {
    public int hammingWeight(int n) {
        int ans = 0;
         while (n > 0) {
            n &= (n - 1);
            ans++;
        }
        return ans;
    }
}

4.综合例题

318.最大单词长度乘积
思路
本题使用位运算的思想来判断两个字符串是否包含相同的字符。首先,创建一个大小与words数组长度相同的整数数组bitWords。然后,遍历words数组,将每个字符串转换为一个整数,用于表示该字符串包含的字符。具体地,对于每个字符串,将其中的每个字符与'a'做差,然后将结果作为二进制位的索引,将相应的位设置为1。这样,整数bitWords[i]就表示了words[i]字符串包含的字符。
接下来,使用两层循环遍历所有的字符串对,并通过位运算判断它们是否包含相同的字符。具体地,计算两个字符串长度的乘积,并将乘积与ans进行比较,更新ans的值。当且仅当两个字符串对应的整数按位与的结果为0时,说明它们不包含相同的字符。最后,返回ans作为结果。
时间复杂度
时间复杂度为O(n^2 * m),其中nwords数组的长度,m是单词的平均长度。
代码实现

class Solution {
    public int maxProduct(String[] words) {
        int[] bitWords = new int[words.length];
        for(int i = 0; i < words.length; i++){
            bitWords[i] = 0;
            for(int j = 0;j < words[i].length(); j++){
                bitWords[i] |= 1 << (words[i].charAt(j) - 'a'); 
            }
        }
        int ans = 0;
        for(int i = 0;i < words.length;i++){
            for(int j = i;j < words.length;j++){
                int temp = words[i].length() * words[j].length();
                if((bitWords[i] & bitWords[j]) == 0) {
                    ans = Math.max(temp,ans);
                }
            }
        }
        return ans;
    }
}

78.子集
思路2二进制法
由于数组中无重复元素,那么我们可以用二进制的位数来表示数组中的元素(n个元素即二进制为2^n,它的子集有2^n个),我们知道二进制是0和1的组合,当某一位为1时说明该位置对应的元素被选择了,由于二进制包含所有的组合,所以将0-2^n中所有的二进制数按照上述规则对应成子集,每一个二进制数字对应一个子集(对应位置为0即不选择,对应位置为1即选择),则可以得到子集的全集,视频讲解点击视频讲解-子集,视频中有详细的模拟举例。
时间复杂度
这段代码的时间复杂度为O(2^n * n),其中n为数组nums的长度。这是因为对于nums数组的每个元素,都有可能在子集中存在或不存在,所以一共有2^n种可能的子集组合,并且在每一种可能中,需要花费O(n)的时间来生成子集。因此,整体的时间复杂度为O(2^n * n)
代码实现

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        int n = nums.length;
        for(int mask = 0;mask < (1 << n); mask++){
            List<Integer> subset = new ArrayList<>();
            for(int i = 0; i < n; i++){
                //(mask & (1 << i)) != 0表示索引为i的位置对应的mask二进制为1,所以将nums[i]加进subset
                if((mask & (1 << i)) != 0) subset.add(nums[i]);
            }
            ans.add(new ArrayList<>(subset));
        }
        return ans;
    }
}

在LeetCode-hot100题解—Day7中还介绍了深度优先遍历的解决方法,相比于上述解法更加高效一点。
137.只出现一次的数字 Ⅱ
思路
使用位运算来统计每个位上数字出现的次数,然后根据出现次数是否为3的倍数来确定只出现一次的数字在该位上的值。最后,将每个位上的值组合起来就得到了只出现一次的数字。简单来说,就是将每个数组元素用二进制表示,然后算出每个数组元素对应位置上1的总数,如果这个数字出现了三次,那么该位的1的个数是3的倍数,如果不是3的倍数,则将该位设置到结果中,举个栗子:
在这里插入图片描述

时间复杂度
时间复杂度为O(n),其中n是数组的长度。
代码实现

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for(int i = 0; i < 32;i++){
            int cnt = 0;
            for(int num : nums){
                cnt += (num >> i) & 1;
            }
            if(cnt % 3 != 0) ans |= (1 << i);
        }
        return ans;
    }
}

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

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

相关文章

MySQL表结构的一些设计经验分享

我们在对一张表进行设计时&#xff0c;还要遵守一些基本的原则&#xff0c;比如经常听见的“范式准则”。但范式准则过于理论&#xff0c;在真实业务中&#xff0c;不必严格遵守三范式的要求。而且有时为了性能考虑&#xff0c;还可以进行反范式的设计&#xff0c;比如在数据仓…

ATFX:美国通胀率平台期,或助力黄金延续涨势

ATFX金属&#xff1a;5月9日19:00至5月10日19:00&#xff0c;COMEX黄金的小时级别出现一波持续24小时的上涨走势&#xff0c;最高触及2385.3美元&#xff0c;累计涨幅2.78%&#xff0c;成为上周最佳的短线交易时机。R阻力线形成后&#xff0c;COMEX黄金进入下降通道&#xff0c…

采油厂职工向媒体投稿的好方法找到了

作为一名采油厂的职工,我深知在媒体上定期投稿的重要性。这不仅是我们展示工作成果、传播企业文化的重要途径,更是上级考核我们工作表现的一项指标。然而,在投稿的过程中,我经历了不少心酸与困扰。 起初,我采用传统的邮箱投稿方式。每天,我都会花费大量时间在网络上搜索合适的媒…

ms17-010(永恒之蓝)

1.漏洞介绍: 永恒之蓝&#xff08;ms17-010&#xff09;爆发于2017年4月14日晚&#xff0c;是一种利用Windows系统的SMB协议漏洞来获取系统的最高权限&#xff0c;以此来控制被入侵的计算机。甚至于2017年5月12日&#xff0c; 不法分子通过改造“永恒之蓝”制作了wannacry勒索病…

n的阶乘(函数)(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//声明n的阶乘函数fac; int fac(int n);int main() {//初始化变量值&#xff1b;int n, result;//获取要阶乘的数&#xff1b;printf("请输入要阶乘的n&…

创新点!CNN与LSTM结合,实现更准预测、更快效率、更高性能!

推荐一个能发表高质量论文的好方向&#xff1a;LSTM结合CNN。 LSTM擅长捕捉序列数据中的长期依赖关系&#xff0c;而CNN则擅长提取图像数据的局部特征。通过结合两者的优势&#xff0c;我们可以让模型同时考虑到数据的时序信息和空间信息&#xff0c;减少参数降低过拟合风险&a…

怎么通过微信小程序实现远程控制8路控制器/断路器

怎么通过微信小程序实现远程控制8路控制器/断路器呢&#xff1f; 本文描述了使用微信小程序调用HTTP接口&#xff0c;实现控制8路控制器/断路器&#xff0c;支持8路输出&#xff0c;均可独立控制&#xff0c;可接入各种电器。 可选用产品&#xff1a;可根据实际场景需求&#…

【2024】Gradle安装配置以及基于Kotlin 进行详细使用

目录&#x1f4bb; 一、介绍二、安装Gradle1、下载安装2、配置环境变量2.1、mac2.2、windows 3、配置国内国内镜像源4、初始化Gradle项目4.1、项目结构4.2、Gradle常用命令 三、项目配置1、配置文件介绍1.1、设置文件settings.gradle1.1.1、单体项目1.1.2、父子项目 1.2、构建文…

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈)

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你…

电子学会C/C++编程等级考试2024年03月(一级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:倒序输出 依次输入4个整数a、b、c、d,将他们倒序输出,即依次输出d、c、b、a这4个数。 时间限制:1000 内存限制:65536 输入 一行4个整数a、b、c、d,以空格分隔。 0 < a,b,c,d < 108 输出 一行4个整数d、c、b、a,整数之间以…

探索人员定位系统的架构设计

随着科技的不断发展&#xff0c;人员定位系统在各个领域中扮演着越来越重要的角色。从室内定位到室外定位&#xff0c;从个人安全到物流管理&#xff0c;人员定位系统为我们提供了精准的位置信息&#xff0c;极大地促进了工作效率和安全管理。 但是&#xff0c;一个成功的人员…

docker 安装 Redis (附图文教程)

首先确保已安装docker 安装docker 拉取 redis 镜像 搜索镜像 docker search redis使用最多人使用的 拉取镜像 没有指定版本默认最新版本 docker pull redis查看镜像 docker images启动容器 创建挂载目录 mkdir -p /home/local/redis/conf /home/local/redis/data创建…

[算法][BFS][leetcode]994. 腐烂的橘子

题目地址 https://leetcode.cn/problems/rotting-oranges/description/ 错误解法 class Solution {public int orangesRotting(int[][] grid) {//层序遍历int ans 0;for (int i 0;i<grid.length;i) {for(int j 0;j<grid[0].length;j){boolean flag false;if(grid[i][j…

python EEL应用程序的启动过程

EEL 启动流程 初始化 EEL (eel.init()): 设定静态文件目录&#xff0c;通常是包含 HTML、CSS、JavaScript 等文件的目录。扫描指定目录下的 JavaScript 文件&#xff0c;寻找通过 eel.expose() 暴露的函数。 启动 Web 服务器 (eel.start()): 基于 Bottle 框架启动一个轻量级的 …

flexible.js+rem页面适配

简介 flexible.js 介绍 flexible.js 是一个用于移动端页面适配的 JavaScript 库&#xff0c;由阿里巴巴团队开发并开源。在移动 web 开发中&#xff0c;由于设备屏幕尺寸、分辨率以及像素比的差异&#xff0c;开发者通常需要编写额外的代码来确保页面在不同设备上都能正确显示…

AR系列路由器配置本地同一网段互通

A R 路由器是华为公司推出的企业级路由器产品系列&#xff0c;具有高可靠性、高性能和易管理等特点。AR 系列路由器提供的功能包括路由转发、安全接入、语音、视频、无线等多种业务&#xff0c;支持各种接入方式和协议&#xff0c;并且可以方便地进行扩展和升级。 实验拓扑图&…

Java面试八股之Java中的IO流分为几种

Java中的IO流分为几种 按数据单位分类&#xff1a; 字节流&#xff08;Byte Stream&#xff09;&#xff1a;以字节&#xff08;8位二进制数&#xff09;为基本单位进行数据读写。字节流适合处理所有类型的数据&#xff0c;包括文本、图像、音频、视频等二进制文件。抽象基类…

微信小程序毕业设计-基于Java后端的微信小程序源码150套(附源码+数据库+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f9e1;今天给大家分享150的微信小程序毕业设计&#xff0c;后台用Java开发&#xff0c;这些项目都经过精心挑选&#xff0c;涵盖了不同的实战主题和用例&#xff0c;可做毕业设…

STM32_HAL_系统定时器(SysTick)_实现计时

1介绍 系统定时器&#xff08;SysTick&#xff09;是ARM Cortex-M处理器系列中的一个特殊定时器&#xff0c;它不属于STM32F1系列微控制器的外设&#xff0c;而是处理器内部的一个组件。SysTick定时器的作用是为操作系统或其他需要精确时钟计数和中断服务的应用提供基础的时间…

半个小时搞懂STM32面经知识——DMA

1.DMA 1.1 什么是DMA&#xff1f; DMA传输将数据从一个地址空间复制到另一个地址空间&#xff0c;提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 CPU无时不刻的在处理着大量的事务&#xff0c;但有些事情却没有那么重要&#xff0c;比方说数据的复制和存储数…