397.整数替换
题目描述
思路
枚举
可以使用递归的方法枚举所有将n变为1的替换序列:
- 当n为偶数时,只有唯一的方法:将n变为n/2。
- 当n为奇数时,可以选择将n增加1或减少1。因为操作完必定将n变为偶数,则下一步必定是n/2,因此可以看成使用两次操作,将n变为(n+1)/2或(n-1)/2。
Java实现
class Solution {
public int integerReplacement(int n) {
if (n == 1) return 0;
if (n % 2 == 0) return 1 + integerReplacement(n / 2);
return 2 + Math.min(integerReplacement(n / 2), integerReplacement(n / 2 + 1));
}
}
Python实现
# 枚举
class Solution:
def integerReplacement(self, n: int) -> int:
if n == 1:
return 0
if n % 2 == 0:
return 1 + self.integerReplacement(n // 2)
return 2 + min(self.integerReplacement(n // 2), self.integerReplacement(n // 2 + 1))
记忆化搜索
给递归加个记忆化,能降低时间复杂度。
java实现
class Solution {
Map<Integer, Integer> memo = new HashMap<Integer, Integer>();
public int integerReplacement(int n) {
if (n == 1) return 0;
if (!memo.containsKey(n)) {
if (n % 2 == 0) {
memo.put(n, 1 + integerReplacement(n / 2));
} else {
memo.put(n, 2 + Math.min(integerReplacement(n / 2), integerReplacement(n / 2 + 1)));
}
}
return memo.get(n);
}
}
Python实现
class Solution:
@lru_cache(None)
def integerReplacement(self, n: int) -> int:
if n == 1:
return 0
if n % 2 == 0:
return 1 + self.integerReplacement(n // 2)
return 2 + min(self.integerReplacement(n // 2), self.integerReplacement(n // 2 + 1))
贪心
分类讨论:
- 当n为偶数,毫无疑问,只操作n/2。
- 当n为奇数,则n除以4的余数为1或3:
- 如果为1,则应该经过两次操作将n变为(n-1)/2。如果将n变为(n+1)/2,则当(n+1)/2为奇数时,必然有以下两种情况:
- 如果下一步操作进行减一除以二,得到(n-1)/4,则从(n-1)/2可以除以2得到同样的结果。
- 如果下一步操作进行加一除以二,则得到(n+3)/4,则从(n-1)/2可以除以二再加一得到同样的结果。
- 如果为3,则应该将n变为(n+1)/2。如果将n变为(n-1)/2,则当(n-1)/2为奇数时,有以下两种情况:
- 如果下一步进行减一除以二的操作,得到(n-3)/4,则可以从(n+1)/2进行除以二再减一得到相同的结果。
- 如果下一步进行加一再除以二的操作,得到(n+1)/4,则可以从(n+1)/2除以二得到相同的结果。
- 因此对于前一种情况,(n-1)/2总是不劣于(n+1)/2。对于后一种情况,(n+1)/2总是不劣于(n-1)/2,但如果当(n-1)/2已经为1,即n=3时,后续就无需进行任何操作,此时将n变为(n-1)/2是最优的。
- 如果为1,则应该经过两次操作将n变为(n-1)/2。如果将n变为(n+1)/2,则当(n+1)/2为奇数时,必然有以下两种情况:
因此可以根据上面的分类讨论,求出n变为1的操作次数即可。
Java实现
class Solution {
public int integerReplacement(int n) {
int ans = 0;
while (n != 1) {
if (n % 2 == 0) {
++ ans;
n /= 2;
} else if (n % 4 == 1) {
ans += 2;
n /= 2;
} else {
if (n == 3) {
ans += 2;
n = 1;
} else {
ans += 2;
n = n / 2 + 1;
}
}
}
return ans;
}
}
Python实现
class Solution:
def integerReplacement(self, n: int) -> int:
ans = 0
while n != 1 :
if n % 2 == 0:
ans += 1
n //= 2
elif n % 4 == 1:
ans += 2
n //= 2
else:
if n == 3:
ans += 2
n = 1
else:
ans += 2
n = n // 2 + 1
return ans