格雷编码
格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。
给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。即使有多个不同答案,你也只需要返回其中一种。
格雷编码序列必须以 0 开头。
示例 1:
输入: 2
输出: [0,1,3,2]
解释:
00 - 0
01 - 1
11 - 3
10 - 2
对于给定的 n,其格雷编码序列并不唯一。
例如,[0,2,3,1] 也是一个有效的格雷编码序列。
00 - 0
10 - 2
11 - 3
01 - 1
示例 2:
输入: 0
输出: [0]
解释: 我们定义格雷编码序列必须以 0 开头。
给定编码总位数为 n 的格雷编码序列,其长度为 2n。当 n = 0 时,长度为 20 = 1。
因此,当 n = 0 时,其格雷编码序列为 [0]。
模拟
class Solution {
public List<Integer> grayCode(int n) {
List<Integer> result = new ArrayList<Integer>() {{add(0);}};
int head = 1;
for (int i = 0; i < n; i++) {
for (int j = head - 1; j >= 0; j--)
result.add(result.get(j) + head);
head <<= 1;
}
return result;
}
}
异或
class Solution {
public List<Integer> grayCode(int n) {
List<Integer> result = new ArrayList<Integer>();
for(int i = 0; i < (1 << n); i++)
result.add(i ^ (i >> 1));
return result;
}
}
数字的补数
给你一个 正 整数 num ,输出它的补数。补数是对该数的二进制表示取反。
示例 1:
输入:num = 5
输出:2
解释:5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2 。
示例 2:
输入:num = 1
输出:0
解释:1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0 。
异或
5的二进制为 0101,其最高的1到最低位全置1,即 0111。二者异或得到 0010
class Solution {
public int findComplement(int num) {
int top = 0, tmp = num;
while (tmp != 0) {
top++;
tmp >>>= 1;
}
return num ^ ((1 << top) - 1);
}
}
Pow(x,n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。
示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3
输出:9.26100
示例 3:
输入:x = 2.00000, n = -2
输出:0.25000
解释:2-2 = 1/22 = 1/4 = 0.25
递归
class Solution {
public double myPow(double x, int n) {
if (n == Integer.MIN_VALUE)
return 1.0 / quickMul(x, Integer.MAX_VALUE) / x;
double result = quickMul(x, Math.abs(n));
return (n >= 0) ? result : 1.0 / result;
}
private double quickMul(double x, int n) {
if (n == 0) {
return 1.0;
}
double y = quickMul(x, n >> 1);
return (n & 1) == 0 ? y * y : y * y * x;
}
}
迭代
class Solution {
public double myPow(double x, int n) {
if (n == Integer.MIN_VALUE)
return 1.0 / quickMul(x, Integer.MAX_VALUE) / x;
double result = quickMul(x, Math.abs(n));
return (n >= 0) ? result : 1.0 / result;
}
private double quickMul(double x, int n) {
double ans = 1.0, y = x;
while (n > 0) {
if (n % 2 == 1)
ans *= y;
y *= y;
n >>= 1;
}
return ans;
}
}
2的幂
给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
示例 1:
输入: 1
输出: true
解释: 20 = 1
示例 2:
输入: 16
输出: true
解释: 24 = 16
示例 3:
输入: 218
输出: false
位移
class Solution {
public boolean isPowerOfTwo(int n) {
int cur = 1;
for (int i = 0; i < 31; i++) {
if (cur == n)
return true;
cur <<= 1;
if (cur > n)
break;
}
return false;
}
}
求模
int 的最大二次幂为 2 30 2^{30} 230,其余二次幂是它的因数。
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (1 << 30) % n == 0;
}
}
去除最右侧的1
class Solution {
public boolean isPowerOfTwo(int n) {
if (n == 0)
return false;
long x = n;
return (x & (x - 1)) == 0;
}
}
保留最右侧的1
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & -n) == n;
}
}
3的幂
给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false 。
整数 n 是 3 的幂次方需满足:存在整数 x 使得 n == 3x
示例 1:
输入:n = 27
输出:true
示例 2:
输入:n = 0
输出:false
示例 3:
输入:n = 9
输出:true
示例 4:
输入:n = 45
输出:false
整数限制
int 中 最大的 3的幂 为 1162261467
class Solution {
public boolean isPowerOfThree(int n) {
return n > 0 && 1162261467 % n == 0;
}
}
4的幂
给定一个整数,写一个函数来判断它是否是 4 的幂次方。如果是,返回 true ;否则,返回 false 。
整数 n 是 4 的幂次方需满足:存在整数 x 使得 n == 4x
示例 1:
输入:n = 16
输出:true
示例 2:
输入:n = 5
输出:false
示例 3:
输入:n = 1
输出:true
位运算
class Solution {
public boolean isPowerOfFour(int n) {
return n > 0 && (n & (n - 1)) == 0 && (n & 0xaaaaaaaa) == 0;
}
}
位运算+数学运算
class Solution {
public boolean isPowerOfFour(int n) {
return n > 0 && (n & (n - 1)) == 0 && n % 3 == 1;
}
}
两整数之和
不使用运算符 + 和 - ,计算两整数 a 、b 之和。
示例 1:
输入: a = 1, b = 2
输出: 3
示例 2:
输入: a = -2, b = 3
输出: 1
递归
异或 为不进位二进制加法,当且仅当两个数的相同为都为1时才有进位,所以用 与运算。
class Solution {
public int getSum(int a, int b) {
if (b == 0)
return a;
int sum = a ^ b;
int carry = (a & b) << 1;
return getSum(sum, carry);
}
}
迭代
class Solution {
public int getSum(int a, int b) {
while (b != 0) {
int carry = (a & b) << 1;
a ^= b;
b = carry;
}
return a;
}
}