java算法OJ(1)位运算


 目录

1.前言

2.正文

2.1位运算符号

2.1俩数相除

2.1.1题目

2.1.2示例

2.1.3题解

2.2二进制求和

2.2.1题目

2.2.2示例

2.2.3题解

2.3只出现一次的数字

2.3.1题目

2.3.2示例

2.3.3题解

2.4只出现一次的数字(进阶版)

2.4.1题目

2.4.2示例

2.4.3 题解

2.6颠倒二进制位

3.小结


 

1.前言

今天来刷一点算法题,今天上手的是一些稍微基础的位运算练习题,关于位运算呢有许多类似于脑筋急转弯的逻辑思路,还是饶有趣味的,废话不多说,直接开始。

2.正文

2.1位运算符号

在算法题目开始之前,我们先基础盘点下位运算的各种操作。

按位与(AND)&

  • 两个操作数的对应位都为1时,结果才为1。
  • 例如:5 & 3,二进制表示为101 & 011,结果是101,即5。

按位或(OR)|

  • 两个操作数的对应位中至少有一个为1时,结果为1。
  • 例如:5 | 3,二进制表示为101 | 011,结果是111,即7。

按位异或(XOR)^

  • 两个操作数的对应位相同则结果为0,不同则结果为1。
  • 例如:5 ^ 3,二进制表示为101 ^ 011,结果是110,即6。

按位非(NOT)~

  • 反转操作数的每一位,将1变为0,0变为1。
  • 例如:~5,二进制表示为11111011(32位补码表示)。

左移(Left Shift)<<

  • 将操作数的二进制表示向左移动指定的位数,右边空出的位补0。
  • 例如:5 << 1,二进制表示为101 << 1,结果是1010,即10。

右移(Right Shift)>>

  • 将操作数的二进制表示向右移动指定的位数,左边空出的位补符号位(正数补0,负数补1)。
  • 例如:5 >> 1,二进制表示为101 >> 1,结果是5,即0。

2.2俩数相除

2.2.1题目

2.2.2示例

2.2.3题解

毕竟刚开始上手位运算算法,很多基本的技巧很不是很熟悉,这里借鉴了评论区一位大哥的思路,非常厉害。

我们先来思考,不通过加减乘除直接运算得到结果,而是通过位运算来解决这个问题,有什么思路呢?

我们可以先拿dividend除以2的31次方开始,此时被除出来的是非常小的数,一步一步向下逼近,直到出现一个n(即循环中的i),使得n>=divisor, 表示我们找到了一个足够大的数,这个数乘以divisor是不大于dividend的,所以我们就可以减去2^n个divisor,依此类推,直到余数小于除数。


下面罗列代码实现思路:

  • 先处理特殊情况:
  1. 当除数或者被除数一个为0,则返回。
  2. 当被除数是范围内最小数且除数为-1,返回答案(该特殊处理的原因是按照以下算法会越界)。
  • 通过用异或来计算是否符号相异。
  • 接着for循环来实现核心思路,当找到n时,对ans以及被除数进行处理。
  • 最后判断正负输出即可。
class Solution {public int divide(int dividend, int divisor) {if(divisor==0||dividend==0){return 0;}//处理特殊情况,处理掉会溢出得情况if(dividend==Integer.MIN_VALUE&&divisor==-1){return Integer.MAX_VALUE;}boolean judge = (dividend^divisor)<0;//判断负数long a = Math.abs((long)dividend);long b = Math.abs((long)divisor);int ans = 0;for(int i = 31;i >= 0;i--){if(a>>i>=b){ans+=(1<<i);a-=b<<i;}}return judge ? -ans : ans;}
}

2.3二进制求和

2.3.1题目

2.3.2示例

2.3.3题解

这道题可以采用比较朴素的思路,将二进制数先转化为十进制数,相加后再转化为二进制数,但这样就没有利用位运算的思想。在正式讲解之前,先让我分享一个Java 中的一个类,

StringBuilder。


StringBuilder 用于创建可变的字符序列。它提供了一个可变长度的字符序列,可以高效地添加、插入和删除字符。append 方法的使用append(int i): 将一个整数追加到 StringBuilder 对象的末尾。


接下来就是模拟二进制在做加法运算时的代码思路是:

  • 创建一个 StringBuilder 对象 ans 来存储结果。

  • 初始化一个变量 ca 为0,用于存储进位。

  • 使用一个 for 循环遍历两个字符串 ab,从它们的末尾开始逐位相加。循环条件是 i >= 0 || j >= 0,确保至少有一个字符串还没有遍历完。

  • 在每次迭代中,计算当前位的和 sum,包括前一次迭代的进位 ca,以及当前位的值(如果索引有效的话)。通过 a.charAt(i) - '0'b.charAt(j) - '0' 将字符转换为整数。

  • sum 除以2得到新的进位值,并将 sum 对2取余得到当前位的结果,追加到 ans 中。

  • 在循环结束后,检查是否有剩余的进位(即 ca 是否为1),如果有,则追加到 ans 中。

  • 最后,使用 ans.reverse().toString()StringBuilder 中的字符序列反转并转换为字符串,因为二进制加法是从最低位到最高位进行的,而字符串是从最高位到最低位存储的。

class Solution {public String addBinary(String a, String b) {StringBuilder ans = new StringBuilder();int ca = 0;for(int i = a.length() - 1, j = b.length() - 1;i >= 0 || j >= 0; i--, j--) {int sum = ca;sum += i >= 0 ? a.charAt(i) - '0' : 0;sum += j >= 0 ? b.charAt(j) - '0' : 0;ans.append(sum % 2);ca = sum / 2;}ans.append(ca == 1 ? ca : "");return ans.reverse().toString();}
}

2.4只出现一次的数字

2.4.1题目

2.4.2示例

2.4.3题解

这道题如果抛开题目中对线性时间复杂度的要求,其实有许多实现思路,比如对出现过的数字都进行标记,哪个数字仅标记一次则为答案。但既然咱们是位运算主题,那咱们就来分享这道题利用位运算的神奇操作。


我们知道,当一个数a与0异或操作时,则返回a;当a与a异或操作时,则返回0。那么我们就有一个大胆的想法,将数组中所有的数字进行异或操作,但凡出现过俩次的数经过异或全部变为0,最终保留下来的数即为最终答案。当时我看完题解的时候,也被这个思路深深的震撼到了。接下来附上代码:

class Solution {public int singleNumber(int[] nums) {int ans = 0;for(int num:nums){ans^=num;}return ans;}
}

还是再感叹一句,这思路绝了。

2.5只出现一次的数字(进阶版)

2.5.1题目

2.5.2示例

2.5.3 题解

这道题是上一道题的进阶版,我们也是按照位运算的思路进行解决问题。

核心思路是我们只需要累计计算各个数字每一位的加和,可以很轻松的出一个结论是,当末位之和取模3时如果正好为0,则仅出现一次的数的该二进制位置也为0;同理如果取模3为1,则仅出现一次的数的该二进制位置也为1.

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

2.6颠倒二进制位

2.6.1题目

2.6.2示例

2.6.3 题解

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

3.小结

今天的分享到这里就结束了哦,喜欢的小伙伴们点点赞点点关注,你的支持就是对我最大的鼓励!

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

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

相关文章

怎么在Proteus中找到排阻

1、打开安装好的Proteus&#xff0c;点击上方菜单栏中的“库”&#xff0c;再选择“从库选取零件”&#xff0c;或者在左侧元件列表中单击鼠标右键&#xff0c;再点击右键菜单中的“从库中挑选”选项。 2、之后会打开元器件库&#xff0c;我们打开类别中的“Resistors”&#x…

方法部分 学习

方法是程序中最小的执行单元 方法的定义调用 public static void 方法名&#xff08;&#xff09;{ 方法体 } 写在main方法外面&#xff0c;在main函数里面直接调用带参数&#xff1a;public static void 方法名&#xff08;int num1 &#xff0c; int num2&am…

付费计量应用过程(Payment Metering Application process)

The Payment Metering Application process is the combination of the business and support processes as the resultant interactions between the business and support functions, which thus describes the dynamic behavior of the system as a whole. 付费计量…

postman中使用Pre-request Script

一、get方法 get请求时 &#xff0c;有多个params&#xff0c;并且有一个参数为sign&#xff0c;这个参数是有其他params拼接之后md5加密得到的&#xff0c;如何通过js语句获取params参数并生成sign。 const CryptoJS require(crypto-js); // 引入 CryptoJS 库进行 MD5 加密…

深度学习(5):逻辑斯蒂回归Logistic

文章目录 一、逻辑斯蒂回归&#xff08;Logistic Regression&#xff09;二、KL 散度&#xff08;相对熵&#xff09;三、交叉熵&#xff08;Cross-Entropy&#xff09;四、关系五、总结 一、逻辑斯蒂回归&#xff08;Logistic Regression&#xff09; 概述 逻辑斯蒂回归是一种…

MiniCPM-V 2.6训练时fuse_adam报错

原本pip install deepspeed安装了0.15.1版本的&#xff0c;但是在进行sft训练的时候还是报错。大概就是fuse_adam这个op编译有错&#xff0c;c版本要大于17什么的&#xff0c;一堆错。看了一堆解决方案尝试后发现如下这样的有用&#xff1a; 1.下载DeepSpeend源码 git clone ht…

《机器学习》周志华-CH8(集成学习)

8.1个体与集成 集成学习(ensemble learning)通过构建并结合多个学习器来完成学习任务&#xff0c;有时也被称为多分类器系统&#xff0c;基于委员会的学习。 同质”集成“&#xff1a;只包含同种类型的个体学习器&#xff0c;同质集成中的个体学习器亦称“基学习器”&#xff0…

WebRTC关键技术及应用场景:EasyCVR视频汇聚平台高效低延迟视频监控解决方案

众所周知&#xff0c;WebRTC是一项开源的实时通信技术&#xff0c;它通过集成音频、视频和数据传输到Web浏览器中&#xff0c;使得实时通信变得简单且无需任何插件或第三方软件。WebRTC不仅是一个API&#xff0c;也是一系列关键技术和协议的集合&#xff0c;它的出现改变了传统…

中断合并参数coalesce_params解释

在网络驱动程序中&#xff0c;中断是指网络设备向处理器发送信号&#xff0c;通知它有数据需要处理。频繁的中断会导致处理器负担过重&#xff0c;从而影响系统性能。为了优化性能&#xff0c;驱动程序可以使用中断合并技术&#xff0c;将多个中断合并为一个&#xff0c;从而减…

docker快速部署zabbix

两台主机 一台作为server 一台作为agent 安装好docker 并保证服务正常运行&#xff0c;镜像正常pull 分析&#xff1a; 部署 Zabbix 容器环境&#xff0c;通常会涉及几个主要组件&#xff1a; MySQL&#xff08;或 MariaDB 数据库&#xff09;、Zabbix Server 和 Zabbix Web I…

【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台

一、介绍 果蔬识别系统&#xff0c;本系统使用Python作为主要开发语言&#xff0c;通过收集了12种常见的水果和蔬菜&#xff08;‘土豆’, ‘圣女果’, ‘大白菜’, ‘大葱’, ‘梨’, ‘胡萝卜’, ‘芒果’, ‘苹果’, ‘西红柿’, ‘韭菜’, ‘香蕉’, ‘黄瓜’&#xff09;…

Redis的一些数据类型(一)

&#xff08;一&#xff09;数据类型 我们说redis是key value键值对的方式存储数据&#xff0c;key是字符串&#xff0c;而value是一些数据结构,那今天就来说一下value存储的数据。 我们数据结构包含&#xff0c;String&#xff0c;hash&#xff0c;list&#xff0c;set和zest但…

macOS与Ubuntu虚拟机使用SSH文件互传

1.ubuntu配置: 安装openssh服务: sudo apt-get install openssh-server -y 查看服务启动状态: systemctl status ssh 2.macOS使用scp连接ubuntu并发送文件 查看ubuntu IP : ifconfigmacOS终端连接ubuntu : sc

第五篇:Linux进程的相关知识总结(1)

目录 第四章&#xff1a;进程 4.1进程管理 4.1.1进程管理需要的学习目标 4.1.1.1了解进程的相关信息 4.1.1.2僵尸进程的概念和处理方法&#xff1a; 4.1.1.3PID、PPID的概念以及特性&#xff1a; 4.1.1.4进程状态 4.1.2进程管理PS 4.1.2.1静态查看进程 4.1.2.1.1自定义…

基于AI网关的智慧煤矿安全监测应用

煤矿安全一直是矿业管理的重中之重。由于煤矿环境的恶劣与复杂性&#xff0c;例如工作中间环节多、设施设备多样且集中、空间狭小、环境闭塞、有害气体隐患、粉尘聚集等&#xff0c;针对煤矿的安全监测和防范时常面临着极大的挑战。 随着AI技术的发展与普及&#xff0c;依托AI实…

优青博导团队指导-组蛋白甲基化修饰、实验设计、实验结果分析、测序分析及SCI论文辅助,精准高效,为农医学科研保驾护航!

组蛋白甲基化修饰工具(H3K4me3 ChIP-seq) 组蛋白甲基化类型也有很多种&#xff0c;包括赖氨酸甲基化位点H3K4、H3K9、H3K27、H3K36、H3K79和H4K20等。组蛋白H3第4位赖氨酸的甲基化修饰(H3K4)在进化上高度保守&#xff0c;是被研究最多的组蛋白修饰之一。

gnome Files管理文件学习

Files文件夹页可以非常高效的使用&#xff0c;接下来介绍一些有用的快捷命令和tricks 首先是快捷键&#xff1a; **Ctrl T**Ctrl N**Ctrl WClose window or tab**Ctrl FSearch**Ctrl LEnter location**BackspaceGo Back to a Previous FolderCtrl Zoom inCtrl -Zoom outCtrl 0…

MISC - 第四天(OOK编码,audacity音频工具,摩斯电码,D盾,盲文识别,vmdk文件压缩)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天继续讲解MISC知识点 FLAG 附件是一张图片&#xff0c;尝试binwalk无果 使用StegSolve工具Data Extract查看时 发现PK字段&#xff0c;是大多数压缩包的文件头点击Save Bin保存zip文件 解压缩失败使用修复软件:htt…

六西格玛绿带培训机构哪家好?记住这2点很重要

在探讨“六西格玛绿带培训机构哪家好”这一议题时&#xff0c;我们不得不深入剖析当前市场上纷繁复杂的培训机构&#xff0c;以及如何选择一家既能提供高质量教学&#xff0c;又能满足个人职业发展需求的机构。六西格玛作为一套严谨的管理方法论&#xff0c;旨在通过减少变异、…

directx修复工具怎么用?不懂dll缺失怎么修复?本文整理了详细的dll修复方法!

DLL错误&#xff0c;相信很多小伙伴都头疼这个问题。 在电脑上运行程序或者打开某个文件时&#xff0c;是不是会看到“缺少xxx.dll”的错误弹窗&#xff1f;这时候大部分小白用户都是懵的&#xff0c;不知道这是出了什么问题&#xff0c;又该如何解决。 dll文件在电脑领域中扮…