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. Tomcat 报错 The APR based Apache Tomcat Native library which allows optimal performance in production environmen

    这个问题在我一次重新装了tomcat和myeclipse时出现 说实话 出现这个问题头大 但是好在解决了 美滋滋 最开始到处寻找各种解决方案 最后直接注释了server.xml中的一行 直接解决这个报 ...

  2. 【SQL server初级】SQL索引(一)

    SQL索引[一](此文章为“数据库性能优化二:数据库表优化”附属文章之一) SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开 ...

  3. 死磕 java同步系列之redis分布式锁进化史

    问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...

  4. 除了Web和Node,JavaScript还能做什么

    前言 提起JavaScript,我们也许经常会想到的是,可以用来写Web页面嘛,又或者,会想起Node.js 这个服务端环境,搞前后端同构. 那么,除此之外, JavaScript还可以做什么?   ...

  5. PHP获取客户端的真实IP

    REMOTE_ADDR只能获取访问者本地连接中设置的IP,如中南民族大学校园网中自己设置的10.X.XXX.XXX系列IP,而这个函数获取的是局域网网关出口的IP地址, 如果访问者使用代理服务器,将不 ...

  6. 在chrome浏览器中调用IE浏览器并访问(openIE.reg自定义协议)

    在谷歌浏览器中有4种方法调用IE浏览器.如下: c++ socket通过浏览器在ie中打开指定url : vb生成exe,url访问exe启动ie并打开指定url : 通过socket实现通过http ...

  7. python基本数据类型及常用功能

    1.数字类型 int -int(将字符串转换为数字) a = " print(type(a),a) b = int(a) print(type(b),b) num = " v = ...

  8. PHP 实现get 和 Post 请求

    1 get get请求比较简单,file_get_contents():即可实现 $tmpUrl = "http://测试url"; # get方法获取信息 $rawGetData ...

  9. centos7升级openssl、openssh常见问题及解决方法

    升级至openssl 1.1.1版本 升级至openssh 8.0版本 openssl version -a   当前查看版本 一.安装telnet (以防升级失败,连不上服务器,建议弄) #查看是否 ...

  10. 树莓派3B/3B+ 清华镜像系统和安装中文输入法Fcitx及Google拼音输入法

    你还在为树莓派无法安装中文输入法而到处找教程吗? 你还在为树莓派每次下载都要远隔重洋获取资源,龟速下载而烦恼吗? 为了解决这个问题,在这篇树莓派教程中,我将手把手叫你怎样安装 清华镜像系统和中文输入法 ...