目录
每日一句
你可以随时转身,但不能一直后退
作者简介
🏡个人主页:XiaoChen_Android
📚学习专栏:力扣专栏
🕒发布日期:2022/8/30
『LeetCode|每日一题』整数替换
1.每日一题
2.解题思路 (枚举法)
2.1 思路分析
刚开始看到这题,我就在草稿本上写出来一系列的数及对应的替换方法,发现了一些规律
S1:如果该数为1,那么返回0即可;
S2:如果该数为偶数,那么该数除以二的同时替换方法数+1即可;
S3:如果该数是奇数的话,我们可以看成两个偶数,这两个数为
和
,用这两个数递归调用函数,取小的那个值,然后最后的结果加上2就行
2.2 核心代码
if (n % 2 == 0) return 1 + integerReplacement(n / 2);
return 2 + Math.min(integerReplacement(n / 2), integerReplacement(n / 2 + 1));
2.3 完整代码
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));
}
}
2.4 运行结果
由结果可以看出,此方法时间复杂度和空间复杂度都还可以进一步优化,下面将介绍另外的方法
3.解题思路(记忆化搜索)
3.1 思路分析
思路和第一种方法类似,就是增加了一个HashMap来记录已经计算过的值,如果该数没有被计算过,那么就把他的值以及整数替换方法数添加进map,这样大大减少了时间的消耗
3.2 核心代码
if(map.containsKey(n) == false){
if(n % 2 == 0){
map.put(n , 1 + integerReplacement(n / 2));
}else {
map.put(n , 2 + Math.min(integerReplacement(n / 2) , integerReplacement(n / 2 + 1)));
}
}
3.3 完整代码
class Solution {
Map<Integer , Integer> map = new HashMap<Integer , Integer>();
public int integerReplacement(int n) {
if (n == 1) return 0;
if(map.containsKey(n) == false){
if(n % 2 == 0){
map.put(n , 1 + integerReplacement(n / 2));
}else {
map.put(n , 2 + Math.min(integerReplacement(n / 2) , integerReplacement(n / 2 + 1)));
}
}
return map.get(n);
}
}
3.4 运行结果
通过对比上一个方法可以看出时间消耗明显减少,所以用HashMap可以减少计算次数
4.解题思路(贪心)
4.1 思路分析
S1:分两种情况讨论:
- 如果该数除二求余为0,那么只有一种方法能获得最少的替换次数;
- 如果该数除二求余不为0,那么又可以分三种情况:
- n % 4 == 1时:我们应将该数变为
,假设变为
,奇数加一除以二还是奇数,
还是奇数,如果下一步是-1再除以2,则变成了
,实际上还是相当于
除以2;如果下一步是+1再除以2,则变成了
, 实际上相当于
除以2再加1;因此得出将该数变为
的结果总是不会差于
;
- n % 4 == 3时:我们应该将该数变为
,假设变为
,
还是个奇数,如果下一步是-1再除以2,则变成了
,实际上还是相当于
除以2再-1;如果下一步是+1再除以2,则变成了
,实际上相当于
除以2;因此得出将该数变为
的结果总是不会差于
;
- 此情况为特殊情况,如果此时n == 3,那么
等于1,就不需要考虑其他情况,直接变成
即可;
3.该方法只需要一个循环即可,只要n != 1时就可以继续循环,额外定义一个变量存替换次数即可
4.2 核心代码
while(n != 1){
if(n % 2 == 0){
ans += 1;
n /= 2;
}else if(n % 4 == 1){
ans += 2;
n = n / 2;
}else {
if(n == 3){
ans += 2;
n = 1;
}else {
ans += 2;
n = n / 2 + 1;
}
}
}
4.3 完整代码
class Solution {
public int integerReplacement(int n) {
int ans = 0;
if(n == 1) return 0;
while(n != 1){
if(n % 2 == 0){
ans += 1;
n /= 2;
}else if(n % 4 == 1){
ans += 2;
n = n / 2;
}else {
if(n == 3){
ans += 2;
n = 1;
}else {
ans += 2;
n = n / 2 + 1;
}
}
}
return ans;
}
}
4.4 运行结果
5.总结
我认为记忆化搜索更容易被人理解,当然贪心算法和记忆化搜索的时间复杂度也是O(log n),相比第一种方法都大大节省了时间的消耗,贪心算法没有用递归,所以也是高效率的解法
🍁 类似题目推荐:
如果文章对各位大佬有帮助就支持一下噢,新手尝试,不好的地方请各位大佬多多指教!