算法通关村第11关【白银】| 位运算高频算法题

news2024/10/7 6:40:15

一、移位的妙用

1.位1的个数

思路:

利用一个数和1与操作,结果就是最低位的特点,每次右移都能知道一位是不是1

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

n-1 将最低位的 '1' 变为 '0',并将低位的 '0' 变为 '1',然后与 n 进行按位与运算,即可将最低位的 '1' 置为 '0'。这个算法的精妙之处在于,它不需要遍历所有的位,而是通过不断地将最低位的 '1' 置为0来计算 '1' 的个数,从而实现了高效的计算。这对于处理大量二进制数据的情况非常有用。

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int count = 0;
        while((n != 0)){
            n = n&(n-1);
            count++;
        }
        return count;  
    }
}

2.比特位计数

思路:从0到n循环执行求位1的个数

class Solution {
    public int[] countBits(int n) {
        int[] ans = new int[n+1];
        for(int i = 0;i<=n;i++){
            int num = i;
            while(num > 0){
                ans[i]++;
                num = num & (num-1);
            }
        }
        return ans;
    }
}

3.颠倒二进制位

思路:不断将 n 的最低位复制到结果的对应位置,实现了二进制位的翻转。值得注意的是,这里处理的是无符号整数,因此不需要考虑符号位,Java使用逻辑移位符号>>>

public int reverseBits(int n) {
    int res = 0; // 用于存储翻转后的结果
    int pos = 31; // 由于 int 是32位,所以从最高位开始处理,即第31位
    while (pos >= 0) { // 从最高位向最低位循环处理
        res += (n & 1) << pos; // (n & 1) 取得 n 的最低位,并将其左移 pos 位
        pos--; // 处理下一位
        n = n >>> 1; // 右移 n,去掉已经处理过的最低位
    }
    return res; // 返回翻转后的结果
}

 二、位实现加减乘除专题

1.两数之和

思路:进位求和+不进位求和

  1. 进入 while 循环,只要 b 不等于0,就继续执行。这个循环会一直执行,直到没有进位产生,也就是 b 变成0。

  2. 在循环中,首先计算进位 carry。进位是通过将 ab 进行按位与操作 a & b,然后将结果左移一位 << 1 得到的。这一步模拟了进位的计算。

  3. 接下来,通过异或操作 a ^ b 求得不包括进位的和。异或操作可以将两个数相加,但不考虑进位。

  4. 将进位 carry 的值赋给 b,以便将进位传递到下一轮循环。

  5. 继续循环,直到没有进位产生,也就是 b 变成0。

  6. 最后,返回 a,即最终的和。

class Solution {
    public int getSum(int a, int b) {
        
        while(b != 0){
            int carry = (a&b)<<1;
            a = a ^ b;
            b = carry;
        }
        return a;
    }
}

以123+623为例:

1. 初始状态:a = 123(二进制 1111011),b = 623(二进制 1001110111)。

2. 进入循环,b 不等于 0:

   - 计算进位 `carry`:(a & b) << 1 = (1111011 & 1001110111) << 1 = (1001011) << 1 = 10010110。

   - 计算不包括进位的和 `a`:a = a ^ b = 1111011 ^ 1001110111 = 1001010100。

   - 将进位传递给 `b`:b = carry = 10010110。

3. 进入下一轮循环,b 不等于 0:

   - 计算进位 `carry`:(a & b) << 1 = (1001010100 & 10010110) << 1 = 10000000 << 1 = 100000000。

   - 计算不包括进位的和 `a`:a = a ^ b = 1001010100 ^ 10010110 = 1001110010。

   - 将进位传递给 `b`:b = carry = 100000000。

4. 进入下一轮循环,b 不等于 0:

   - 计算进位 `carry`:(a & b) << 1 = (1001110010 & 100000000) << 1 = 100000000 << 1 = 1000000000。

   - 计算不包括进位的和 `a`:a = a ^ b = 1001110010 ^ 100000000 = 1001110010。

   - 将进位传递给 `b`:b = carry = 1000000000。

5. 进入下一轮循环,b 不等于 0:

   - 计算进位 `carry`:(a & b) << 1 = (1001110010 & 1000000000) << 1 = 1000000000 << 1 = 10000000000。

   - 计算不包括进位的和 `a`:a = a ^ b = 1001110010 ^ 1000000000 = 1001110010。

   - 将进位传递给 `b`:b = carry = 10000000000。

6. 进入下一轮循环,b 不等于 0:

   - 计算进位 `carry`:(a & b) << 1 = (1001110010 & 10000000000) << 1 = 0 << 1 = 0。

   - 计算不包括进位的和 `a`:a = a ^ b = 1001110010 ^ 0 = 1001110010。

   - 将进位传递给 `b`:b = carry = 0。

7. 进入下一轮循环,b 等于 0,循环结束。

8. 返回最终结果 `a`,即 1001110010 对应的十进制数,结果是 746。

所以,123 + 623 的结果是 746,这个算法成功地完成了加法操作。

2.递归乘法

普通解法,将乘法转换成多次加法

class Solution {
    public int multiply(int A, int B) {
        int res = 0;
        if(A>B){
            int t = A;
            A = B;
            B =t;
        }
        while(A-->0){
            res += B;
        }
        return res;
    }
}

思路:【优化】将两个数相乘的过程转化为一系列的加法和移位操作,从而减少了乘法运算的次数

n = a0*2^0 + a1*2^1 + a2*2^2 + a3*2^3........+ak*2^k

拆分成2的幂的和的方法是将乘法操作分解成了多次左移和加法操作,这是一种基于二进制的思考方式,也是快速乘法的一部分。

举例说明:13 * 12 = 13 * (8 + 4) = 13 * 8 + 13 * 4 = (13 << 3) + (13 << 2)

这个示例中,我们首先将12分解为8和4,然后用13分别乘以8和4。在二进制视角下,8可以表示为2的三次方(8 = 2^3),4可以表示为2的二次方(4 = 2^2)。因此,我们可以将这个乘法操作分解为两个左移和相加的操作。

  1. 首先,将13左移3位,得到13 * 8 = (13 << 3)。
  2. 接下来,将13左移2位,得到13 * 4 = (13 << 2)。
  3. 最后,将这两个部分相加,即(13 << 3) + (13 << 2),就得到了13 * 12的结果。

这种方法充分利用了二进制的特性,通过左移和相加的方式来实现乘法操作,从而提高了计算效率。

  1. 首先,将13和12转换为二进制数。13的二进制表示是1101,12的二进制表示是1100。

  2. 初始化结果为0。

  3. 从右往左,第一个数为0,进行2次幂,13*2。

  4. 第二个数的最右位是0,进行2次幂,13*2*2。

  5. 第二个数的下一位是1,乘数的二进制现在为0011,这时我们将结果加上,(最低位碰到1说明一次拆分完成要相加了)结果变为13*2*2(进行了4次加法)。

  6. 乘数对半减小0001,被乘数进行2次幂,13*2*2*2

  7. 接下来是第三位,同样是1,这时将结果再次加上13*2*2*2(8次加法),结果变为13*2*2(4次)+13*2*2*2(8次)。

  8. 最后一位是0,不进行任何操作。

  9. 现在,我们已经完成了所有位的计算,结果是13*12。

例如:14*127(11111111)/ (1+2+4+8+16+32+64)

14*127 = 14*1+14*2+14*4+14*8+14*16+14*32+14*64

14*125(11111101)= 14*1+14*4+14*8+14*16+14*32+14*64

class Solution {
    public int multiply(int A, int B) {
        int min = Math.min(A,B);
        int max = Math.max(A,B);
        int ans = 0;
        while(min!=0){
            //奇数相加
            if((min&1) == 1){
                ans += max;
            }
            min = min >> 1; //对半减小乘数
            max += max; //进行2的幂次
        }
        return ans;
    }
}

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

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

相关文章

密码学入门——环游密码世界

文章目录 参考书目一、基本概念1.1 本书主要角色1.2 加密与解密 二、对称密码与公钥密码2.1 密钥2.2 对称密码和公钥密码2.3 混合密码技术 三、其他密码技术 参考书目 图解密码技术 第三版 一、基本概念 1.1 本书主要角色 1.2 加密与解密 加密 解密 密码破译 二、对称密…

grid网格布局的使用?

一、定义 CSS 网格是一个用于 web 的二维布局系统。利用网格&#xff0c;你可以把内容按照行与列的格式进行排版。另外&#xff0c;网格还能非常轻松地实现一些复杂的布局。 网格是由一系列水平及垂直的线构成的一种布局模式。根据网格&#xff0c;我们能够将设计元素进行排列…

Ubuntu系统下使用宝塔面板实现一键搭建Z-Blog个人博客的方法和流程

文章目录 1.前言2.网站搭建2.1. 网页下载和安装2.2.网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测试5.结语 1.前言 Ubuntu系统作…

单向链表和双向链表的增删改查以及排序问题

文章目录 单向链表双向链表运行结果完整代码 本文介绍链表的增删改查以及排序问题&#xff0c;其中最重要的还是指针的使用&#xff01; 单向链表 定义一个单向链表&#xff0c;里面包含一个整型数据和一个指向后向的指针。 typedef struct linklist{int data;struct linkli…

InnoDB 的默认隔离级别是什么?

分析&回答 大部分数据库系统&#xff08;如Oracle&#xff09;都将都将读提交&#xff08;Read-Commited&#xff09;作为默认隔离级别&#xff0c;而MySQL却选择可重复读&#xff08;Repeatable-Read&#xff09;作为其默认隔离级别。 如果没有隔离级别基础知识的话先看…

数学建模之插值法

目录 1 插值法概述2 插值法原理3 拉格朗日插值4 牛顿插值5 三次Hermite插值&#xff08;重点&#xff09;6 三次样条插值&#xff08;重点&#xff09;7 各种插值法总结8 n 维数据的插值9 插值法拓展10 课后作业 1 插值法概述 数模比赛中&#xff0c;常常需要根据已知的函数点进…

【Unity3D赛车游戏优化篇】新【八】汽车实现镜头的流畅跟随,以及不同角度的切换

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

YOLOV8实例分割——详细记录环境配置、自定义数据处理到模型训练与部署

前言 Ultralytics YOLOv8是一种前沿的、最先进的&#xff08;SOTA&#xff09;模型&#xff0c;它在前代YOLO版本的成功基础上进行了进一步的创新&#xff0c;引入了全新的特性和改进&#xff0c;以进一步提升性能和灵活性。作为一个高速、精准且易于操作的设计&#xff0c;YO…

合宙Air724UG LuatOS-Air LVGL API控件-标签 (Label)

标签 (Label) 标签是 LVGL 用来显示文字的控件。 示例代码 label lvgl.label_create(lvgl.scr_act(), nil) lvgl.label_set_recolor(label, true) lvgl.label_set_text(label, "#0000ff Re-color# #ff00ff words# #ff0000 of\n# align the lines …

Vision Transformer(VIT 网络架构)

论文下载链接&#xff1a;https://arxiv.org/abs/2010.11929 文章目录 引言1. VIT与传统CNN的比较2. 为什么需要Transformer在图像任务中&#xff1f; 1. 深入Transformer1.1 Transformer的起源&#xff1a;NLP领域的突破1.2 Transformer的基本组成1.2.1 自注意机制 (Self-Atte…

C++将派生类赋值给基类

在 C/C++ 中经常会发生数据类型的转换,例如将 int 类型的数据赋值给 float 类型的变量时,编译器会先把 int 类型的数据转换为 float 类型再赋值;反过来,float 类型的数据在经过类型转换后也可以赋值给 int 类型的变量。 数据类型转换的前提是,编译器知道如何对数据进行取舍…

星际争霸之小霸王之小蜜蜂(十)--鼠道

系列文章目录 星际争霸之小霸王之小蜜蜂&#xff08;九&#xff09;--狂鼠之灾 星际争霸之小霸王之小蜜蜂&#xff08;八&#xff09;--蓝皮鼠和大脸猫 星际争霸之小霸王之小蜜蜂&#xff08;七&#xff09;--消失的子弹 星际争霸之小霸王之小蜜蜂&#xff08;六&#xff09;-…

大数据课程K20——Spark的SparkSql概述

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Spark的SparkSQL由来; ⚪ 了解Spark的SparkSQL特点; ⚪ 了解Spark的SparkSQL优势; ⚪ 掌握Spark的SparkSQL入门; 一、SparkSQL概述 1. 概述 Spark为结构化数据处理引入了一个称…

SQLI-labs-第四关

知识点&#xff1a;get双引号(")和括号注入 思路&#xff1a; 1、判断注入点 首先&#xff0c;输入?id1 --&#xff0c;看看正常的回显状态 接着输入?id1 --&#xff0c;结果还是正常回显&#xff0c;说明这里不存在单引号问题 试试双引号&#xff0c;这里爆出了sql语…

深入了解GCC编译过程

关于Linux的编译过程&#xff0c;其实只需要使用gcc这个功能&#xff0c;gcc并非一个编译器&#xff0c;是一个驱动程序。其编译过程也很熟悉&#xff1a;预处理–编译–汇编–链接。在接触底层开发甚至操作系统开发时&#xff0c;我们都需要了解这么一个知识点&#xff0c;如何…

C# 如何读取dxf档案

需求来源&#xff1a; 工作中&#xff0c;客户提供一张CAD导出的dxf 档案&#xff0c;然后需要机器人将其转成点位&#xff0c;走到对应的位置。 下面介绍一下dxf档案到底是什么&#xff1f;以及语法规则。 dxf 格式介绍&#xff1a;DXF 格式 dxf LINE 格式。 其实上述文档…

软考:中级软件设计师:多媒体基础,音频,图像,颜色,多媒体技术的种类,图像音频视频的容量计算,常见的多媒体标准

软考&#xff1a;中级软件设计师:多媒体基础 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &am…

在公网上使用SSH远程连接安卓手机Termux:将Android手机变身为远程服务器

文章目录 前言1.安装ssh2.安装cpolar内网穿透3.远程ssh连接配置4.公网远程连接5.固定远程连接地址 前言 使用安卓机跑东西的时候&#xff0c;屏幕太小&#xff0c;有时候操作不习惯。不过我们可以开启ssh&#xff0c;使用电脑PC端SSH远程连接手机termux。 本次教程主要实现在…

介绍OpenCV

OpenCV是一个开源计算机视觉库&#xff0c;可用于各种任务&#xff0c;如物体识别、人脸识别、运动跟踪、图像处理和视频处理等。它最初由英特尔公司开发&#xff0c;目前由跨学科开发人员社区维护和支持。OpenCV可以在多个平台上运行&#xff0c;包括Windows、Linux、Android和…

高等数学刷题

分段函数主要看在临界点处的左右极限是否相等&#xff0c;若相等则整段函数即为连续 &#xff08;反之若是连续函数&#xff0c;在某一点为间断点&#xff0c;则可推导出一定为可去间断点&#xff09; 无定义的点一定为间断点 如果该点有极限则为可去间断点 由于x的不确定导…