1. 问题描述:
给定一个正整数 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-replacement
2. 思路分析:
① 一开始想到模拟整个过程,如果n为偶数那么n / 2,如果为奇数那么n - 1这样可以尽可能逼近1,但是这个做法实际上是忽略了一点就是有可能n为奇数加1之后有可能可以连续除以2的,也就数4的倍数,比如15就是这样一个例子,所以上面的做法是不正确的,然后想到题目中n为奇数的时候其实是有两种选择的,所以我们可以尝试这两种选择看最终能够使得n到达的最少步数是多少,因为需要尝试当前状态下n - 1还是n - 1最终能够使得步数最少,所以是可以递归来解决的(尝试所有的可能性最终得到最优解)
② 我们可以写有返回值的递归与没有返回值的递归方法,没有返回值的递归我们可以声明一个类变量,并且在方法中声明一个变量来记录到达当前的n需要的步数,到达递归出口的时候也就是n <= 3的时候与类变量的值进行比较,假如更小那么更新类变量,在具体的实现中我们可以判断出当前的数字是奇数还是偶数,假如是偶数那么直接除以2,如果是奇数那么依次调用n - 1与n + 1的递归方法尝试可能性
有返回值的递归方法其实也是类似的,只是在递归的时候需要返回对应的结果,为偶数的时候方法返回值为往下进行递归的结果加1,为奇数的时候方法返回值为递归n - 1与n + 1的递归结果中较小的结果加上1,
3. 代码如下:
有返回值:
class Solution:
# 有返回值的递归
def recursion(self, n: int):
if n <= 3: return n - 1
if n % 2 == 0: return self.recursion(n // 2) + 1
else:
return min(self.recursion(n - 1), self.recursion(n + 1)) + 1
def integerReplacement(self, n: int) -> int:
return self.recursion(n)
无返回值:
class Solution:
# 类变量用来记录n变为1的最少的次数
count = 0
# cur变量用来记录变为当前数字需要的次数
def recursion(self, n: int, cur: int):
if n == 1:
if cur < self.count:
self.count = cur
return
if n <= 0: return
if n % 2 == 0: self.recursion(n // 2, cur + 1)
else:
self.recursion(n - 1, cur + 1)
self.recursion(n + 1, cur + 1)
def integerReplacement(self, n: int) -> int:
self.count = n
self.recursion(n, 0)
return self.count