369,整数替换
想了解更多数据结构以及算法题,可以关注微信公众号“数据结构和算法”,每天一题为你精彩解答。也可以扫描下面的二维码关注
给定一个正整数 n,你可以做如下操作:
\1. 如果 n 是偶数,则用 n / 2替换 n。
\2. 如果 n 是奇数,则可以用 n + 1或n - 1替换 n。
n 变为 1 所需的最小替换次数是多少?
示例 1:
输入:
8
输出:
3
解释:
8 -> 4 -> 2 -> 1
示例 2:
输入:
7
输出:
4
解释:
7 -> 8 -> 4 -> 2 -> 1
或
7 -> 6 -> 3 -> 2 -> 1
01
答案
public int integerReplacement(int n) {
if (n == Integer.MAX_VALUE)
return 32;
if (n <= 3)
return n - 1;
if (n % 2 == 0)
return integerReplacement(n / 2) + 1;
else
return Math.min(integerReplacement(n - 1), integerReplacement(n + 1)) + 1;
}
解析:
使用递归的方式很容易理解,当n是偶数的时候非常简单,我们只需要让n/2代替n即可。当n是奇数的时候,我们取n-1,和n+1计算次数的最小值即可。
其实这道题我们还可以换种思路。当n是奇数的时候,比如n=2k+1;无论是加1还是减1,结果都会是偶数,这个偶数有可能是4的倍数,有可能只是2的倍数(比如6,10等)。我们为了减少计算次数要尽可能多的往4的倍数上靠。所以当n%4=3的时候我们让n加1,当n%4=1的时候我们让n减1。当n等于3的时候是个例外,因为
3→2→1要比3→4→2→1替换次数少。所以我们计算的时候要把n=3的情况单独处理,我们来看下代码
02
另一种思路的递归写法
public int integerReplacement(int n) {
if (n == Integer.MAX_VALUE)
return 32;
if (n <= 3)
return n - 1;
if (n % 2 == 0)
return integerReplacement(n / 2) + 1;
else
return (n & 2) == 0 ? integerReplacement(n - 1) + 1 : integerReplacement(n + 1) + 1;
}
03 另一种思路的非递归写法
public int integerReplacement(int n) {
int count = 0;
while (n > 1) {
if ((n & 1) == 0) {//是偶数
n /= 2;
} else {//是奇数
if (((n + 1) & 3) == 0 && n != 3) {//对3求余为0
n = n / 2 + 1;
count++;
} else {
n--;
}
}
count++;
}
return count;
}
上面的3种实现方式其实都很简单,我们看到在判断n%4=3的时候有多种实现方式,我们还可以来列举一下(下面的n首先是奇数,判断才没问题),如果判断结果为true,那么n对4求余的结果就是3。
1,n%4==3;
2,(n+1)&3==0;
3,(n&2)!=0;
4,Integer.bitCount(n + 1) <= Integer.bitCount(n -
1)(Integer.bitCount是判断二进制中1的个数,也可以参照前面讲的364,位1的个数系列(一))5,((n >>1) & 1) != 0