原文链接
https://www.geekxh.com/0.0.%E5%AD%A6%E4%B9%A0%E9%A1%BB%E7%9F%A5/01.html
这里是把这个大佬的题解用java写一下做个记录
位运算篇
连续n个数的和
求 1 2 … n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例 1:
输入: n = 3 输出: 6
解题思路: 递归,A&&B,A为true,那么返回B的布尔值,A为false,那么返回false,所以我们把递归的返回条件设置成A,递归的主体就是B
也就是:
class Solution {
public int sumNums(int n) {
boolean b = n > 0 && ((n + = sumNums(n - 1)) > 0);
return n;
}
}
第231题:2的幂
给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
示例 1:
输入: 1
输出: true
解释: 20 = 1
解题思路:
方法一:判断n%2为0时,n/=2的结果是不是1。
class Solution {
public boolean isPowerOfTwo(int n) {
if (n == 0) return false;
while (n % 2 == 0) n /= 2;
return n == 1;
}
}
方法二: 对于N为2的幂的数,都有 N&(N-1)=0。
class Solution {
public boolean isPowerOfTwo(int n) {
return n >0 && (n&(n-1))==0;
}
}
第191题:位1的个数
编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
解题思路:
方法一:利用掩码来计算,碰到掩码mask&n!=0说明这位是1,计数。最后返回结果。
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int result = 0;
//初始化掩码为1
int mask = 1;
for (int i = 0; i < 32; i++) {
if ((n & mask) != 0) {
result++;
}
mask = mask << 1;
}
return result;
}
}
方法二: 根据上一题的思路,n&n(n-1)进行位运算,那么最低位的1会变成0。我们计数又多少次这样成立就ok。
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int count = 0;
while(n != 0)
{
n =(n & (n - 1)) ;
count++;
}
return count;
}
}
第136题:只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
解题思路:用异或,自己和自己异或是0,剩下的就是结果
class Solution {
public int singleNumber(int[] nums) {
int ans=0;
for(int num:nums)
ans^=num;
return ans;
}
}
第137题:只出现一次的数字Ⅱ
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。说明:你的算法应该具有线性时间复杂度。你可以不使用额外空间来实现吗?
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
解题思路:
方法一:哈希表,存储元素和次数,然后再遍历找到那个次数为1的。
class Solution {
public int singleNumber(int[] nums) {
HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int num:nums)
{
map.put(num,map.getOrDefault(num,0)+1);
}
for(int k:map.keySet())
if(map.get(k)==1) return k;
return -1;
}
}
方法二: 数学,[A,A,A,B,B,B,C,C,C] 和 [A,A,A,B,B,B,C],差了两个C。即:
3×(a b c)−(a a a b b b c)=2c,也就是去重后数组的和x3-现在数组的和是c的两倍。
class Solution {
public int singleNumber(int[] nums) {
Set<Long> set=new HashSet<>();
long sumSet=0,sumArr=0;
for(int num:nums)
{
sumArr+=num;
set.add((long)num);
}
for(long s:set) sumSet+=s;
return (int)((sumSet*3-sumArr)/2);
}
}
方法三:位运算。
。。。。。。。。。。。。。
第268题:缺失数字
给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。
示例 1:
输入: [3,0,1]
输出: 2
解题思路:
方法一:1到n的和是(n+1)n/2,我们算出总的和,然后减去这个数组的和,剩下的就是我们要求的。因为有一个0,所以数组的长度也就是1到n的长度。
3 0 1 作为例子,n(n+1)/2的结果是6,然后数组的结果是4,所以差2。
class Solution {
public int missingNumber(int[] nums) {
int len=nums.length;
int sum=(len+1)*len/2;
int tsum=0;
for(int num:nums)
tsum+=num;
return sum-tsum;
}
}
方法二:异或,假设是n然后用 ans^ =nums[i]^ i来找到那个值。
3 0 1作为例子 3^ (3 ^ 0) ^ (0 ^1) ^ (1 ^ 2),结果就是2,括号里是nums[i] ^ i。
class Solution {
public int missingNumber(int[] nums) {
int ans=nums.length;
for(int i=0;i<nums.length;i++)
ans^=nums[i]^i;
return ans;
}
}