LeetCode刷题笔记(3)Java位运算符与使用按位异或(进制之间的转换)
1.问题描述
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
算法应该具有线性时间复杂度并且不使用额外空间。
输入: [4,1,2,1,2]
输出: 4
2.解题思路
这道题的主要的难点是具有线性时间复杂度并且不能使用额外的空间,因此就排除了很多的方法。
当时使用双指针尝试了以下,但是并没有取得成功,因为最后的结果可能是错误的。
3.正确解题思路
使用“按位异或”,即Java中的‘^’运算符来进行计算。
由于异或的原则是,不同为1,相同为0,题目中给定的数组中,如果两个相同的数异或的结果一定为0,最后得到的结果就是只出现一次的元素。
public int singleNumber(int[] nums) {
int res = nums[0];
for (int i = 1; i < nums.length; i++) {
res ^= nums[i];
}
return res;
}
4.另外的一个例子
需要找出t中不在s中的那个字符。
输入:
s = "abcd"
t = "abcde" 输出:
e
也可以用按位异或的方式进行计算
public char findTheDifference(String s, String t) {
char c = 0;
for (int i = 0; i < s.length(); ++i) {
c ^= s.charAt(i);
}
for (int i = 0; i < t.length(); ++i) {
c ^= t.charAt(i);
}
return c;
}
5.问题描述
不使用“+”“-”运算符计算两个整数的和。
(1)自己的思路:模拟计算机实际来操作二进制数补码的加法
Integer.parseInt无法将一个负数的补码转换成原始的负数,否则会报错java.lang.NumberFormatException
此时,只能这么来计算:取反码,然后加1,转换成相反数,然后添加上一个符号“-”
// System.out.println(new e371().getSum(a, b));
System.out.println("11111111111111111111111111101100".length());
System.out.println(Integer.toBinaryString(-20));
// System.out.println(Integer.parseInt("11111111111111111111111111101100", 2));
System.out.println(Integer.parseInt("00000000000000000000000000010100", 2));
解题思路:模仿实际计算机的真实计算结果,超级麻烦!!!!!!
class Solution {
public int getSum(int a, int b) {
String aStr = Integer.toBinaryString(a);
String bStr = Integer.toBinaryString(b);
String longStr = (aStr.length() < bStr.length()) ? bStr : aStr;
String shortStr = (aStr.length() < bStr.length()) ? aStr : bStr;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < longStr.length() - shortStr.length(); i++) {
sb.append(0);
}
shortStr = sb.toString().concat(shortStr);
boolean isUp = false;
StringBuffer resSB = new StringBuffer();
for (int i = longStr.length() - 1; i >= 0; i--) {
if (!isUp) {
if (longStr.charAt(i)== '1' && shortStr.charAt(i) == '1') {
isUp = true;
resSB.append(0);
} else {
resSB.append(Integer.valueOf(longStr.charAt(i)) ^ Integer.valueOf(shortStr.charAt(i)));
}
} else {
if (longStr.charAt(i) == '1' && shortStr.charAt(i) == '1') {
isUp = true;
resSB.append(1);
} else if (longStr.charAt(i) == '0' && shortStr.charAt(i)== '0') {
resSB.append(1);
isUp = false;
} else {
resSB.append(0);
isUp = true;
}
}
}
if (isUp && resSB.length() < 32) resSB.append(1);
String result = resSB.reverse().toString();
if (result.length() < 32) {
return Integer.parseInt(result, 2);
}
if (result.charAt(0) == '0') {
return Integer.parseInt(result, 2);
} else {
StringBuffer sbsb = new StringBuffer();
for (char c : result.toCharArray()) {
if (c == '1') {
sbsb.append(0);
} else {
sbsb.append(1);
}
}
result = sbsb.toString();
longStr = result;
shortStr = "00000000000000000000000000000001";
boolean isUp_1 = false;
StringBuffer resSB_1 = new StringBuffer();
for (int i = longStr.length() - 1; i >= 0; i--) {
if (!isUp_1) {
if (longStr.charAt(i)== '1' && shortStr.charAt(i) == '1') {
isUp_1 = true;
resSB_1.append(0);
} else {
resSB_1.append(Integer.valueOf(longStr.charAt(i)) ^ Integer.valueOf(shortStr.charAt(i)));
}
} else {
if (longStr.charAt(i) == '1' && shortStr.charAt(i) == '1') {
isUp_1 = true;
resSB_1.append(1);
} else if (longStr.charAt(i) == '0' && shortStr.charAt(i)== '0') {
resSB_1.append(1);
isUp_1 = false;
} else {
resSB_1.append(0);
isUp_1 = true;
}
}
}
result = resSB_1.reverse().toString();
return -Integer.parseInt(result, 2);
}
}
}
(2)更好的思路,使用位运算符
public int getSum(int a, int b) {
if(b == 0){ //没有进位的时候完成运算
return a;
}
int sum,carry;
sum = a^b; //完成第一步加法的运算
carry = (a&b)<<1; //完成第二步进位并且左移运算
return getSum(sum,carry);//
}
根据实际例子分析这块代码:
(1)a=1,b=2
a-> 00000000 00000000 00000000 00000001
b-> 00000000 00000000 00000000 00000010
b=2
sum-> 00000000 00000000 00000000 00000011
a&b-> 00000000 00000000 00000000 00000000
carry-> 00000000 00000000 00000000 00000000 输出sum=3 (2)a=1,b=7
a-> 00000000 00000000 00000000 00000001
b-> 00000000 00000000 00000000 00000111
a&b-> 00000000 00000000 00000000 00000001
sum-> 00000000 00000000 00000000 00000110
carry-> 00000000 00000000 00000000 00000010 a&b-> 00000000 00000000 00000000 00000010
sum-> 00000000 00000000 00000000 00000100
carry-> 00000000 00000000 00000000 00000100
a&b-> 00000000 00000000 00000000 00000100
sum-> 00000000 00000000 00000000 00000000
carry-> 00000000 00000000 00000000 00001000
a&b-> 00000000 00000000 00000000 00000000
sum-> 00000000 00000000 00000000 00001000
carry-> 00000000 00000000 00000000 00000000 输出sum = 8 (3)a=-16,b=14
a-> 11111111111111111111111111110000
b-> 00000000000000000000000000001110
a&b-> 00000000000000000000000000000000
sum-> 11111111111111111111111111111110
carry-> 0 输出sum=-2
6.Java位运算符
(1)"~(按位取反)"
~(-14) == 13(int类型)
-14(原码):10000000 00000000 00000000 00001110
-14(反码):11111111 11111111 11111111 11110001
-14(补码):11111111 11111111 11111111 11110010
非过程(同时为1才为1):00000000 00000000 00000000 00001101
十进制表示为:1+4+8=13
(2)"&(按位与)"
5&-4 == 4(int类型)
-4(原码):10000000 00000000 00000000 00000100
-4(反码):11111111 11111111 11111111 11111011
-4(补码):11111111 11111111 11111111 11111100
5 : 00000000 00000000 00000000 00000101
-4: 11111111 11111111 11111111 11111100
与过程(同时为1才为1):
00000000 00000000 00000000 00000100
十进制表示为:4
(3)"|(按位或)"
3|6 == 7(int类型)
3: 00000000 00000000 00000000 00000011
6: 00000000 00000000 00000000 00000110
或过程(只要有1就为1):
00000000 00000000 00000000 00000111
十进制表示为:1+2+4=7
(4)"^(按位异或)"
10^3 == 9(int类型)
3 : 00000000 00000000 00000000 00000011
10: 00000000 00000000 00000000 00001010
异或过程(不同为1相同为0):
00000000 00000000 00000000 00001001
十进制表示为:1+8=9
(5)"<<(左移,低位添0补齐)"
-2<<3 == -16(int类型)
-2 : 11111111 11111111 11111111 11111110
<<过程:111(舍弃) 11111111 11111111 11111111 11110 000(补零)
十进制表示为:-16
(6)">>(右移,高位添符号位)"
15>>2 == 3(int类型)
15 : (符号位是0)00000000 00000000 00000000 00001111
>>过程:00(补两个0) 000000 00000000 00000000 00000011 11(舍弃最末位两个11)
十进制表示为:1+2=3
(7)">>>(右移,高位添0补齐)"
4>>>2 == 1(int类型)
4 : 00000000 00000000 00000000 00000100
>>>过程:00(补两个0) 000000 00000000 00000000 00000001 00(舍弃最末位两个00)
十进制表示为:1
LeetCode刷题笔记(3)Java位运算符与使用按位异或(进制之间的转换)的更多相关文章
- matlab学习笔记10_6 字符串与数值间的转换以及进制之间的转换
一起来学matlab-matlab学习笔记10 10_6 字符串与数值间的转换以及进制之间的转换 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合 ...
- LeetCode刷题笔记和想法(C++)
主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...
- Java基础知识强化106:Java中 int 的各进制之间的转换
1.二.八.十.十六进制之间的转换 下面是示例代码,我们直接通过JDK工具库中的方法实现的,如下: public static Integer valueOf(String s, int radix ...
- LeetCode刷题总结-双指针、位运算和分治法篇
本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. ...
- LeetCode刷题笔记 - 12. 整数转罗马数字
学好算法很重要,然后要学好算法,大量的练习是必不可少的,LeetCode是我经常去的一个刷题网站,上面的题目非常详细,各个标签的题目都有,可以整体练习,本公众号后续会带大家做一做上面的算法题. 官方链 ...
- 18.9.10 LeetCode刷题笔记
本人算法还是比较菜的,因此大部分在刷基础题,高手勿喷 选择Python进行刷题,因为坑少,所以不太想用CPP: 1.买股票的最佳时期2 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. ...
- leetcode刷题笔记342 4的幂
题目描述: 给定一个整数 (32位有符整数型),请写出一个函数来检验它是否是4的幂. 示例:当 num = 16 时 ,返回 true . 当 num = 5时,返回 false. 问题进阶:你能不使 ...
- 【leetcode刷题笔记】Excel Sheet Column Number
Related to question Excel Sheet Column Title Given a column title as appear in an Excel sheet, retur ...
- 【leetcode刷题笔记】Best Time to Buy and Sell Stock II
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
随机推荐
- 数据分析--pandas的基本使用
一.pandas概述 1.pandas是一个强大的Python数据分析的工具包,是基于NumPy构建的. 2.pandas的主要功能 具备对其功能的数据结构DataFrame.Series 集成时间序 ...
- JsonMessageView工具类
前言 工具类 示例: 前端发送ajax请求 springmvc控制层接收请求并处理请求 前言: 在工作中使用springmvc web框架时常常会发送一个ajax请求,我们在控制层接收到请求并 ...
- 虚拟机ubuntu 网速慢的解决方法
其实虚拟机网速慢,我觉得就两个限制因素.一个是虚拟机的内存,内存小了,上传和下载的速率就慢了,就像内存小的虚拟机跑得慢是一个道理:还有一个就是网络连接方式,这里我使用的是桥接,之前我使用的NAT模式, ...
- ouc_software第一次作业:OUC二手物品交易
一.前言 1.项目名称:ouc二手物品交易 2.项目简介 (1)创办一个网上校内二手物品交易平台,供校内师生进行交易二手物品. (2)经过身份认证的用户,可将自己想要交易的二手物品发布至平台,供其他用 ...
- 02-21 决策树ID3算法
目录 决策树ID3算法 一.决策树ID3算法学习目标 二.决策树引入 三.决策树ID3算法详解 3.1 if-else和决策树 3.2 信息增益 四.决策树ID3算法流程 4.1 输入 4.2 输出 ...
- 洛谷 P3745 [六省联考2017]期末考试
题目描述 有 nnn 位同学,每位同学都参加了全部的 mmm 门课程的期末考试,都在焦急的等待成绩的公布. 第 iii 位同学希望在第 tit_iti 天或之前得知所有课程的成绩.如果在第 tit_ ...
- 安装高可用Hadoop生态 (二) 安装Zookeeper
2. 安装Zookeeper 2.1. 解压程序 ※ 3台服务器分别执行 .tar.gz -C/opt/cloud/packages /opt/cloud/bin/zookeeper /conf ...
- 编程杂谈——std::vector与List<T>的性能比较
昨天在比较完C++中std::vector的两个方法的性能差异并留下记录后--编程杂谈--使用emplace_back取代push_back,今日尝试在C#中测试对应功能的性能. C#中对应std:: ...
- 文本分类(TFIDF/朴素贝叶斯分类器/TextRNN/TextCNN/TextRCNN/FastText/HAN)
目录 简介 TFIDF 朴素贝叶斯分类器 贝叶斯公式 贝叶斯决策论的理解 极大似然估计 朴素贝叶斯分类器 TextRNN TextCNN TextRCNN FastText HAN Highway N ...
- Spring Cloud OAuth2 实现用户认证及单点登录
文章较长,建议推荐,建议转发,建议收藏,建议关注公众号哈. OAuth 2 有四种授权模式,分别是授权码模式(authorization code).简化模式(implicit).密码模式(resou ...