题目描述:
给定一个正整数 n ,你可以做如下操作:
如果 n 是偶数,则用 n / 2替换 n 。
如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。
n 变为 1 所需的最小替换次数是多少?
原题链接:
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-replacement
解题思路:
这题是按照官方题解写出来的,只能说在我根本没有思路的时候,看到这题解我实在是懵了,位运算和递归是我一生之敌,想不到怎么写的题位运算和递归总能以“短小精悍”的形式出现在你面前!!!
下面是我自对本题的总结回顾,添加了一些官方没有提到的更详细的说明。
如果n是偶数,递归将n替换成n / 2,每次递归返回+1,如此递归的次数就相当于计算的次数,因为每次递归都加1,。如果是奇数,可以将n替换成(n + 1)/ 2 或者 (n - 1)/ 2,题目问的是替换次数,不论是加一还是减一,都算一次,然后除以二又算一次,所以 每次递归返回+2。
注意,此处需要有个细节处理,由于题目给出的n取值范围包括2 - 1,所以取(n + 1)/ 2时会越界,因为整形int取值范围小于等于2
- 1,所以这里换成了n / 2 + 1,n为奇数时计算的值和(n + 1)/ 2的值时一样的。因为计算时会自动向下取整。(n - 1)/ 2也同理换成了 n / 2。
代码如下 :
class Solution {
public int integerReplacement(int n) {
//递归结束条件(即开始条件)
if (n == 1) return 0;
//如果n是偶数,只要一直除以二即可,每递归一次返回一个1+;记录的相当于递归次数。
if (n % 2 == 0) {
return 1 + integerReplacement(n / 2);
}
//这里是n为奇数的情况下,注意这里并不代表只有第一次是奇数,比如(7 - 1)/ 2 = 3;也是奇数,只要是奇数就会先走一步(- 1),再走一步(/ 2),替换了两次才能变成偶数,所以这里每次递归碰到奇数返回的数字是2。
return 2 + Math.min(integerReplacement(n / 2 +1),integerReplacement(n / 2));
}
}