复盘二进制的习题(2)

338 Counting Bits。输入一个整数n,对于 0 ≤ i ≤ num,计算每个数的二进制1的个数。例如:num = 5 返回 [0,1,1,2,1,2]。希望能在O(n)的时间内完成。这里有动态规划的思想。
思路一:

十进制数二进制表示
00000
10011+(0的bits)
20101
30111+(1的bits)
41001
51011+(1的bits)
61101+(2的bits)
71111+(3的bits)
810001
9100011+(1的bits)
10100101+(2的bits)
11100111+(3的bits)

观察可以发现,值为2n的时候,1的位数为1。其他情况下数,就是1+【从0开始的数1的位数】。

public int[] countBits3(int num) {int[] r = new int[num+1];int p = 1,i=0;while(p<=num){if((p&(p-1))==0) i=0;r[p++] = 1+r[i++];}return r;
}

思路二:发现一个规律:,7=111 ,由011->111添加了1个1;6=110,由011->110,1的个数不变,但是1的位置变了。从0daonum是一个不断变换1的位置或者不断加1的过程,这样就将任意一个数i,与i/2联系起来了。

public int[] countBits(int num) {int[] r = new int[num+1];for(int i =1;i<=num;i++){r[i] = r[i/2]+(i&1);}return r;
}

i&1,当数字为偶数就加0,如果是奇数就加1。

318 Maximum Product of Word Lengths。最大的单词长度乘积。输入一个字符串数组words,返回最大的length(words[i])*length(words[j]),ij,并且单词i和单词j不含有公共字符。
思路一:难点是判断两个字符串是否包含相同字母。可以一个个遍历找到,效率会比较低。看看用位运算能怎么做。一共26个小写字母。表示不同的字母可以用one-hot类型表示(从词向量表示方法得到的启示)。

z = 10000…000(一共25个0)
y = 01000…000(一共25个0)

a = 0000…001

用26位的二进制表示不同的字母。
这样一个字符串 abc = 000….111
azc = 100…..101
两个字符串的值做与操作。如果结果为0,则说明没有相同字符。

public int maxProduct(String[] words) {int n = words.length;int[] values = new int[n];for (int i = 0; i < n; i++) {for (int j = 0; j < words[i].length(); j++) {values[i] |= (1 << (words[i].charAt(j) - 'a'));}}int maxproduct = 0;for (int i = 0; i < n - 1; i++) {for (int j = i + 1; j < n; j++) {if ((values[i] & values[j]) == 0) {if (words[i].length() * words[j].length() > maxproduct) {maxproduct = words[i].length() * words[j].length();}}}}return maxproduct;}

137 Single Number II。给定一个数组,每个数字出现三次,只有一个数字出现了一次。找到这个数字。
思路一:以前有个题目是说每个字母出现两次,只有一个字母出现了一次。这样用异或操作,就能找到只出现了一次的字母。但是出现三次?这里方法不管用了。
 计算数组中所有数字的每一bit1的个数。1=01,如果数组中有三个1,那么第0位的1就有3个,3%3=0。你肯定会问题如果数组中有三个1和3呢?那第0位的1就会有6个,6%3=0。但是如果只有2个3,那第0位的1就只有5个,5%3!=0。那3就是要找的数字了。

public int singleNumber(int[] nums) {int result = 0;for (int j = 0; j < 32; j++) {int sum = 0;for (int i = 0; i < nums.length; i++) {sum += ((nums[i] >> j) & 1);}result += ((sum % 3)<<j);}return result;
}

260 Single Number III。输入数组nums,每个数字都恰好出现了两次。但是有两个数字,都只出现了一次。找到这两个数字。
思路:记录只出现了1次的两个数分别为a,b。
 出现了2次的时候,找不同,肯定需要异或操作。对所有nums的元素做异或,最后得到的是r=a|b。如果r的第i位等于1,那说明a和b在这个位置是有分歧的。我们利用这一个bit就可以将nums数组分为第i位是0和第i位是1,两个部分。这个时候再做异或,就能去掉出现了两次的数,留下只有一次的数。
 只留下一个数某一位为1,其他都为0,的操作是:n &=-n
 

public int[] singleNumber(int[] nums) {int[] ans = new int[2];int diff = 0;for (int num : nums) {diff ^= num;}diff &= -diff;for (int num : nums) {if ((num & diff) == 0) {ans[0] ^= num;} else {ans[1] ^= num;}}return ans;
}

78 subsets
思路:求子集,就是将数组中每一个元素,或者取或者不取,组合起来。从二进制的角度来表示。例如nums=[1,2,3]。下标分别是 0,1,2。每次取一个,2个,三个就遍历完成了。
用1表示取这一位的数字。

下标: 0 1 2
组合 0 0 0 =0
1 0 0 =4
0 1 0 =2
0 0 1 =1
1 1 0 =6
1 0 1 =5
0 1 1 =3
1 1 1 =7

 发现下标用0 1 表示后的值就是从0到7. 7=2^3-1。所以找到规律。
 做了这么久,第一次直接找到最佳回答。
 显然还可以用深度优先搜索的思路理解。
 

public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> result = new ArrayList<List<Integer>>();int n = nums.length;int total = (1<<n)-1;for(int i=0;i<=total;i++){List<Integer> list = new ArrayList<Integer>();for(int j=0;j<n;j++){if(((i>>j) &1)==1){list.add(nums[j]);}}result.add(list);}return result;}

总结:这次关于二进制习题的复盘就结束了。整个做题的过程还是比较沮丧的。平时二进制操作用的比较少。前面的习题基本都是得看答案才能知道二进制该怎么用。这些操作在笔记中,用加粗符号标记出来了。当习题做到中间的时候,已经开始能想到用什么操作,能实现什么功能了。但是还不能完全做对。到了最后终于能找到感觉了。这也说明了练习,总结,才能掌握一门技巧。多次练习、总结终会学到一门技巧。解决问题过程中,对规律的观察和总结,是解题的关键。

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

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

相关文章

c#XML的基本使用

创建XML文档 static void Main(string[] args){//1.引入命名空间//2.创建XML文档对象XmlDocument xmldoc new XmlDocument();//3.创建第一行描述信息&#xff0c;添加到xmldoc文档中XmlDeclaration xmldec xmldoc.CreateXmlDeclaration("1.0", "utf-8", …

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

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

linux 进入一个中文乱码的目录的方法

bash命令&#xff1a;cd ls | awk NRxxx awk命令&#xff1a;获取第xxx行的目录名称&#xff0c;加上NR表示从第一行开始读的行号取 NR已经读出的记录数&#xff0c;就是行号&#xff0c;从1开始 用|把ls的结果传给后面的awk命令&#xff0c;连接上前面的cd就能进入啦 导引号…

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

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

第五章数理统计--样本和抽样分布

从今天开始要学习数理统计。 概率论&#xff1a;是专门研究随机现象的一门学科&#xff0c;定量描述随机现象及其规律。 数理统计&#xff1a;数理统计的研究对象是数据&#xff0c;包括对数据的采集、整理、分析、建模。主要任务是获取样本、描述样本&#xff0c;从样本得到…

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 现在…

第六章 参数估计

依据样本推出总体分布的参数&#xff0c;方法有两种&#xff1a;矩估计和极大似然估计。  参数估计的形式有&#xff1a;点估计和区间估计。  点估计&#xff1a;构造合适的统计量θˆθˆ(X1,X2,...Xn)用来估计未知参数θ&#xff0c;θˆ称为参数θ的点估计量。  当给定…

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

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

Python拷贝梳理

python中存在与其他语言不同的概念&#xff0c;现在梳理一下相关概念。 其中 变量&#xff1a;拥有指向对象的连接空间&#xff0c;即引用空间的代称。 引用&#xff1a;指变量指向对象的指针。 对象&#xff1a;指变量声明后所产生的内存空间。 可变对象&#xff1a;表示…

sql一对多查询

子查询返回的值不止一个。当子查询跟随在 、!、<、<、>、> 之后&#xff0c;或子查询用作表达式时&#xff0c;这种情况是不允许的。 正确写法&#xff1a; select Material_Manage.MaterialNum,Material_Manage.MaterialName,Material_Manage.MaterialWeight,Mate…

[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 …

第四十五期:程序员未来干什么?做架构还是做管理?

很多程序员应该都会有这个疑问&#xff0c;尤其是工作经验不多的&#xff0c;对未来充满了期待。在我职业生涯的早期&#xff0c;比较偏重于走管理路线&#xff1b;现在呢&#xff0c;成了公司的架构师&#xff0c;当然也会承担一部分的管理工作。 很多程序员应该都会有这个疑问…

leetcode之回溯backtracing专题1

39 Combination Sum 给一组整数&#xff0c;给一个目标整数。从数组中任意选择几个数&#xff0c;这几个数的和等于目标整数。数组中每个数字可以选择多次。  例如given candidate set [2, 3, 6, 7] and target 7, 返回 [ [7], [2, 2, 3] ] 思路&#xff1a;数组candidat…

第十九期: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…

leetcode之回溯backtracing专题2

46 Permutations 输入一个不重复的数组 &#xff0c;写出这个数组的排列&#xff0c;不能重复。  例如 输入nums[1,2,3]&#xff0c;输出 [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 思路&#xff1a;可以看到 第0位&#xff08;从左开始数&#xff…

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

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