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位运算符与使用按位异或(进制之间的转换)的更多相关文章

  1. matlab学习笔记10_6 字符串与数值间的转换以及进制之间的转换

    一起来学matlab-matlab学习笔记10 10_6 字符串与数值间的转换以及进制之间的转换 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合 ...

  2. LeetCode刷题笔记和想法(C++)

    主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...

  3. Java基础知识强化106:Java中 int 的各进制之间的转换

    1.二.八.十.十六进制之间的转换  下面是示例代码,我们直接通过JDK工具库中的方法实现的,如下: public static Integer valueOf(String s, int radix ...

  4. LeetCode刷题总结-双指针、位运算和分治法篇

    本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. ...

  5. LeetCode刷题笔记 - 12. 整数转罗马数字

    学好算法很重要,然后要学好算法,大量的练习是必不可少的,LeetCode是我经常去的一个刷题网站,上面的题目非常详细,各个标签的题目都有,可以整体练习,本公众号后续会带大家做一做上面的算法题. 官方链 ...

  6. 18.9.10 LeetCode刷题笔记

    本人算法还是比较菜的,因此大部分在刷基础题,高手勿喷 选择Python进行刷题,因为坑少,所以不太想用CPP: 1.买股票的最佳时期2 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. ...

  7. leetcode刷题笔记342 4的幂

    题目描述: 给定一个整数 (32位有符整数型),请写出一个函数来检验它是否是4的幂. 示例:当 num = 16 时 ,返回 true . 当 num = 5时,返回 false. 问题进阶:你能不使 ...

  8. 【leetcode刷题笔记】Excel Sheet Column Number

    Related to question Excel Sheet Column Title Given a column title as appear in an Excel sheet, retur ...

  9. 【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 ...

随机推荐

  1. CocosCreator实现动物同化

    获取源码 关注微信公众号『一枚小工 』,发送『动物同化 』获取完整游戏源码. 游戏玩法 游戏目标是将游戏区域的动物全部同化成同一种动物.游戏从左上角开始,从右边点击需要变成的目标动物头像,如果被同化动 ...

  2. liunx帮助whatis使用方法

           liunx帮助             获取帮助的能力决定了技术的能力! 1.whatis ♢只显示命令的简短描述,相对功能比较单一. [09:42:22 root@centos ~]# ...

  3. Android Studio [跑马灯]

    MainActivity package com.xdw.secondapp; import android.graphics.Paint; import android.support.v7.app ...

  4. 小记redis持久化的机制

    刚学redis,就经常看到两种持久化机制在眼头晃,RDB和AOF,然而当时学的还知道这两东西是啥玩意,过段时间又忘了,中文记忆这两种概念总感觉有些别扭.今心血来潮翻看redis的配置文件,豁然开朗,仿 ...

  5. Spring boot 官网学习笔记 - Configuration Class(@import)

    推荐使用 Java-based configuration ,也可以使用xml we generally recommend that your primary source be a single ...

  6. layDate——初步使用

    layui系列中layDate的使用教程网址 https://www.layui.com/laydate/ 我这里简单举例: 1.引入js <script type="text/jav ...

  7. 【SQL基础】char,nchar,vchar,nvchar之间的区别

    (1)       定义: char:    固定长度,存储ANSI字符,不足的补英文半角空格. nchar:   固定长度,存储Unicode字符,不足的补英文半角空格 varchar:  可变长度 ...

  8. 如果有人问你 JFinal 如何集成 EhCache,把这篇文章甩给他

    废话不多说,就说一句:在 JFinal 中集成 EhCache,可以提高系统的并发访问速度. 可能有人会问 JFinal 是什么,EhCache 是什么,简单解释一下. JFinal 是一个基于Jav ...

  9. linux下安装Elasticsearch

    一.简单介绍: Elasticsearch提供了近乎实时的数据操作和搜索功能,es集群中所有节点可以一起提供索引和搜索功能,能够相互发现彼此和自动地加入到集群中 二.基础概念: 1.索引: 表征的文档 ...

  10. Scala 多继承顺序

    Trait多继承顺序: 准则: 如果有超类,则先调用超类的函数. 如果混入的trait有父trait,它会按照继承层次先调用父trait的构造函数. 如果有多个父trait,则按顺序从左到右执行. 所 ...