复盘二进制的习题(1)

  本文是对近期二进制专题的leetcde习题的复盘。文中的解决思路来源于leetcode的讨论,以及一些网页。
342 判断一个整数(32bits)是否是4的次幂。
 写出4i,i=0,1,2,3,4...的二进制表示,查找规律。会发现这些数的特征是 a 都>0;b 只有一位是1,代码:n&(n-1)==0;c 1都在奇数位置,如果从1开始数,代码:n&(0x55555555)!=0。

191 数数一个无符号整数n的二进制表示中有几个1。
 方法一:每次判断最末位置是否为1:n&1==1=>最末位是1;接着n=n>>1,继续判断。
 方法二:每次判断n的某一个位置,从最末位开始。n&1!=0=>该位是1;接着计算(n&(1<<1)),再继续n&(1<<2),如此下午,判断32个位置。方法一和二思路是相同的,都是通过位移来判断不同的位置,都需要32次循环,只是一个移动数字,一个移动掩码mask。
 方法三:如果数字n的二进制位只有1位是1,循环32次太浪费了。n&(n-1) 实际上是把一个数的最低位的有效1,给去掉了;而且一次还只能去掉一个位置上的1。这样只要n=(n&(n-1)),n不等于0,就知道1的位数是加1的。
 思考:如果是有符号的呢?

136 Single Number。给定的数组中,每个数都出现了两次,只有一个数出现了一次。找到只出现了一次的数。
 方法:两个相同的数异或之后会是0。所有数字异或之后加和,留下的数就是要找的数。

461 Hamming Distance。海明距离是计算两个int,都多少个位是不同的。
 方法:任意两个数异或之后不同的位会变为1。步骤是:n=(i^j);数n有几个1,等同于191。
 
169 Majority Element. 主元素是指在数组中出现次数超过n/2的元素。前提假设:数组不为空;主元素总数存在。(这题做过,怎么一点印象都没有)
 方法1:循环计算nums[i]出现次数。时间复杂度O(n2)
 方法2:用hashmap,保存每个数字出现次数。时间复杂度O(n),空间复杂度O(n)
 方法3:先排序,再找到最长的连续串。时间复杂度O(nlogn)
 方法4:分治法,数组一分为2,查找第一部分的主元素A,第二部分的主元素B。如果A的次数=B的次数,A和B都是候选主元素。如果不同,则选出主元素。时间复杂度O(nlogn)
 方法5:随机选元素(不甚理解)。平均时间复杂度O(n),最坏是无穷。随机啊。。。。
 方法6:Moore Voting algorithm。定义候选元素element和次数count。不断遍历nums,如果count=0,element=当前元素,count=1;如果count>0,当前元素=element则count++;否则count–。留下的element一定是主元素。时间复杂度O(n)。这个想法太奇妙了。有点像双方交战,主元素是一方,其他元素是一方。不断增加或者减少count。
 方法7:位运算。直接上代码吧。有点不会描述了。一个int,32位。哪个位置上1的个数>n/2,那这一位一定是主元素贡献的。所以只要找到1出现次数超过n/2的位,其他位置为0,就可以找到主元素。 

public int majorityElement(int[] nums) {int[] bit = new int[32];for (int i = 0; i < nums.length; i++) {for (int j = 0; j < 32; j++) {bit[j] += (nums[i] >> j) & 1;}}int majority = 0;for (int j = 0; j < 32; j++) {bit[j] = bit[j] > (nums.length / 2)? 1 : 0;majority += bit[j] << j;}return majority;}

405 将一个整数用十六进制表示
 方法:做十进制与十六进制基础元素的映射。做映射有两种方式,一种是map,一种是数组。当key是数字的时候用数组还是比较方便的。nums[]={0,1,2,….a,b,…f}。数组的下标正好是十六进制对应的十进制。

接着十六进制可以用4位二进制表示。每次将num与0x0f做与操作,这样就能只留下最后四位了。

public String toHex(int num) {if(num==0) return "0";char[] hexadecimalChar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };String r = "";while (num != 0) {r = hexadecimalChar[num & 0x0f] + r;num >>>= 4;}return r;}

190 给定一个无符号的整数num,输出一个整数out,这个整数是输入数字的二进制的逆转。如果方法要多次调用,可以怎么优化。
 方法一:变量r为最后结果,从num低位开始,每次处理1位,r<<1+最低位处理的值。循环32次。 

public int reverseBits(int n) {int result = 0;for (int i = 0; i < 32; i++) {result <<= 1;result += n&1;n >>>=1;}return result;}

 多次调用优化的方法应该是存储字节与结果的映射关系。
 方法二:可以先看代码。来自网页。每4位当做一个整体处理,int32位分为8个部分:abcdefgh。处理顺序是:abcdefgh -> efghabcd -> ghefcdab -> hgfedcba。代码最后两行是处理:4位内部的倒序。
 这思路看到后真是震惊。原来分治法还能这么玩。膜拜啊。
 

public int reverseBits(int n) {n = (n >>> 16) | (n << 16);n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8);n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4);n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2);n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1);return n;}

476 Number Complement。一个int的补是指二进制取反。但是高位的0不变。例如5的补是2。因为 5=101 ,取反,010=2。但是一个int有32位,对于5,从第4位开始的0都不算。所以需要知道最高位的1,在哪个位置即可。
  下面是两种解法。

public int findComplement(int num) {return ~num & (Integer.highestOneBit(num)  - 1);
}public int findComplement2(int num) {int mask = Integer.MAX_VALUE;while((num & mask) !=0){mask <<=1;}System.out.println(~mask);return ~num & (~mask);
}

401 Binary Watch。二进制手表。好酷的手表。这是一个穷举搜索的问题。
时:8 4 2 1 。每一个选与不选分别用1和0 表示。这样就形成了一个一个的二进制数。如果说时钟只有一个灯亮,那么选择可能有:
时:8 4 2 1
f1: 0 0 0 1
f2: 0 0 1 0
f3: 0 1 0 0
f4: 1 0 0 0

231 判断一个数是否是2的平方。2的平方的特征是:a 大于0;2 只有一个1。

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

389 Find the Difference。输入两个字符串s、t。t是s中所有字母随机排列后组成的字符串,但是t中有一个字符在s中没有出现。找出在t中没有出现的那个字符。
思路一:用map。遍历s中每个字符的出现次数,保存在map中。接着遍历t中的字符串,将map[key]value值减1。如果在map的key值不存在或者说map[key]的value <=0 ,那这个字符一定不在s中出现。
思路2:位操作。用异或可以将相同的字符抵消。s和t两个字符串做异或,留下的就是没在s中出现的字符。

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

268 Missing Number。给一个包含n个不同数值的数组nums,数组本应该是0,1,2,…n这样的数字,但是丢了一个数字。返回丢失的数字。例如输入 nums = [0, 1, 3] 返回2。
思路:这个题目与上一提很相似。389是查找多出的字符,268是查找丢失的数字。都是从两个可比较的对象中,查找出多的或者少的部分。

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

371 Sum of Two Integers。不用+ - 操作求两个数的和。这个解法就是比较神奇了。处理两个数相同的部分;处理两个数相异的部分。两个数相同的部分加和的时候还要向前进一,和我们手动计算和相似。

public int getSum(int a, int b) {return b == 0 ? a : getSum(a ^ b, (a & b) << 1);
}

参考资料

1 bit-manipulation
2 网址
3 网址
可能会有落下的网址,未列出。谢谢作者们。

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

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

相关文章

第十六期:简单的介绍一下大数据中最重要的MapReduce

MapReduce是分布式运行的&#xff0c;由两个阶段组成&#xff1a;Map和Reduce&#xff0c;Map阶段是一个独立的程序&#xff0c;有很多个节点同时运行&#xff0c;每个节点处理一部分数据。 MapReduce执行流程图 概述 MapReduce是一种分布式计算模型&#xff0c;由Google提出…

【数据结构与算法】快排、归并 O(nlogn) 基于比较

冒泡、插入、选择 O(n^2) 基于比较 快排、归并 O(nlogn) 基于比较 计数、基数、桶 O(n) 不基于比较 一、分治思想 1.分治思想&#xff1a;分治&#xff0c;顾明思意&#xff0c;就是分而治之&#xff0c;将一个大问题分解成小的子问题来解决&#xff0c;小的子问题解决了&…

第四章切比雪夫不等式、大数定理、中心极限定理

切比雪夫不等式 设随机变量X具有数学期望E(X)μ&#xff0c;方差D(X)σ2&#xff0c;对于任意ε>0&#xff0c;都有P{|X−μ|≥ε}≤σ2ε2方差越大&#xff0c;X落在区间外的概率越大&#xff0c;X的波动也就越大&#xff0c;与方差的意义统一了。等价公式P{|X−μ|<ε}…

第十七期:记一次生产环境SQL Server服务器卡顿问题解决--内存分配不当

概述 最近有台数据库做了迁移&#xff0c;然后运维人员过了一段时间发现这台服务器非常卡&#xff0c;连远程登录都要很久&#xff0c;下面记录下其中的解决过程。 1、查看资源情况 可以发现内存爆满了&#xff0c;而排名第一的正是sqlserver的进程 2、查看sqlserver内存分配…

leetcode 42 接雨水 单调栈

接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#xff0c;在这种情况下&#xff0c;可以接 6 个单位的雨水&#xff08;蓝色部分表示雨水…

第十八期:网页禁止复制粘贴怎么办?教你六招轻松搞定

经常在网上遇到一些无法复制的文章&#xff0c;那么问题来了&#xff0c;有什么办法可以绕开这种限制&#xff0c;将网页内容轻松下载回来呢&#xff1f; 经常在网上遇到一些无法复制的文章&#xff0c;那么问题来了&#xff0c;有什么办法可以绕开这种限制&#xff0c;将网页内…

[Leetcode][第99题][JAVA][恢复二叉搜索树][中序遍历]

【问题描述】[困难] 【解答思路】 1. 显示中序遍历 时间复杂度&#xff1a;O(N) 空间复杂度&#xff1a;O(N) class Solution {public void recoverTree(TreeNode root) {List<Integer> nums new ArrayList<Integer>();inorder(root, nums);int[] swapped find…

第四十一期:深度解析5G核心网建设难点和挑战

目前核心网处于架构转型和业务转型的关键期。在架构层面&#xff0c;NFV、CU分离、边缘计算等技术的成熟推动核心网络架构转型&#xff0c;控制面进一步集中&#xff0c;转发面进一步下沉。 目前核心网处于架构转型和业务转型的关键期。在架构层面&#xff0c;NFV、CU分离、边缘…

[Leetcode][第696题][JAVA][计算二进制子串][分组]

【问题描述】[简单] 【解答思路】 1. 按字符分组 将字符串 ss 按照 00 和 11 的连续段分组&#xff0c;存在counts 数组中&#xff0c;例如 s 00111011&#xff0c;可以得到这样的counts 数组&#xff1a;counts{2,3,1,2}。 这里counts 数组中两个相邻的数一定代表的是两种…

Scrapy安装报错

python3 pip 安装Scrapy在win10 安装报错error: Microsoft Visual C 14.0 is required. Get it with "Microsoft Visual C Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools 问题描述 当前环境win10&#xff0c;python_3.6.1&#xff0c;64…

第四十三期:2020年企业面临的20大数据安全风险

为了帮助企业为日益增长的确定性风险做好准备&#xff0c;以下我们总结了企业2020年可能面临的20种数据安全风险。 如今&#xff0c;数据安全已成为公司、消费者和监管机构的头等大事。 近年来数据泄露和隐私事故越来越普遍&#xff0c;而且代价高昂。Risk Based Security的一…

[Leetcode][第93题][JAVA][复原IP地址][剪枝][回溯]

【问题描述】[中等] 【解答思路】 1. 递归 回溯剪枝 复杂度 class Solution {static final int SEG_COUNT 4;List<String> ans new ArrayList<String>();int[] segments new int[SEG_COUNT];public List<String> restoreIpAddresses(String s) {segmen…

函数嵌套

目录 一、函数的嵌套定义二、函数的嵌套调用一、函数的嵌套定义 函数内部定义的函数&#xff0c;无法在函数外部使用内部定义的函数。 def f1():def f2():print(from f2)f2()f2() # NameError: name f2 is not defined def f1():def f2():print(from f2)f2()f1() from f2 现在…

第四十四期:1.3万亿条数据查询如何做到毫秒级响应?

知乎&#xff0c;在古典中文中意为“你知道吗?”&#xff0c;它是中国的 Quora&#xff0c;一个问答网站&#xff0c;其中各种问题由用户社区创建&#xff0c;回答&#xff0c;编辑和组织。 图片来自 Pexels 作为中国最大的知识共享平台&#xff0c;我们目前拥有 2.2 亿注册用…

[Leetcode][第130题][JAVA][被围绕的区域][DFS][BFS]

【问题描述】[中等] 【解答思路】 1. 深度优先搜索 使用深度优先搜索实现标记操作。在下面的代码中&#xff0c;我们把标记过的字母 O 修改为字母 A。 复杂度 class Solution {int[] dx {1, -1, 0, 0};int[] dy {0, 0, 1, -1};public void solve(char[][] board) {int n …

第十九期:HTTPS虐我千百遍,我却待她如初恋!

本篇将讨论 HTTPS 的加解密原理&#xff0c;很多人都知道 RSA&#xff0c;以为 HTTPSRSA&#xff0c;使用 RSA 加解密数据&#xff0c;实际上这是不对的。 图片来自 Pexels HTTPS 是使用 RSA 进行身份验证和交换密钥&#xff0c;然后再使用交换的密钥进行加解密数据。 身份验…

[Leetcode][第546题][JAVA][移除盒子][递归][动态规划]

【问题描述】[困难] 【解答思路】 1. 递归 动态规划 class Solution {public int removeBoxes(int[] boxes) {int[][][] dp new int[100][100][100];return calculatePoints(boxes, dp, 0, boxes.length - 1, 0);}public int calculatePoints(int[] boxes, int[][][] dp, int…

第二十期:核心交换机的链路聚合、冗余、堆叠、热备份

链路聚合是将两个或更多数据信道结合成一个单个的信道&#xff0c;该信道以一个单个的更高带宽的逻辑链路出现。 一、链路聚合 链路聚合是将两个或更多数据信道结合成一个单个的信道&#xff0c;该信道以一个单个的更高带宽的逻辑链路出现。 链路聚合一般用来连接一个或多个带…

[Leetcode][第20题][JAVA][有效的括号][栈][HashMap]

【问题描述】[中等] 【解答思路】 1. 栈 如果是一个合法的括号序列&#xff0c;遍历到一个右括号(i)时&#xff0c;那么它的前一个括号(i-1)必定是它的另一半(左括号)。反之不是它的另一半或者前面没有括号时&#xff0c;那这个序列必定是非法括号序列。 思路&#xff1a;利用…

springBoot修改代码不需要重启-热部署

springboot每次修改代码都需要重启项目&#xff0c;进行热部署后就不需要每次修改代码都要重启项目了 热部署&#xff1a; 需要在pom.xml里进行配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools&…