夯实算法-整数替换

298 阅读1分钟

题目:整数替换

给定一个正整数 n ,你可以做如下操作:

  1. 如果 n **是偶数,则用 n / 2替换 n **。
  2. 如果 n **是奇数,则可以用 n + 1n - 1替换 n 。

返回 n **变为 1 所需的 最小替换次数 。

示例 1:

输入: n = 8
输出: 3
解释: 8 -> 4 -> 2 -> 1

示例 2:

输入: n = 7
输出: 4
解释: 7 -> 8 -> 4 -> 2 -> 17 -> 6 -> 3 -> 2 -> 1

示例 3:

输入: n = 4
输出: 2

提示:

  • 1<=n<=23111 <= n <= 2^{31} - 1

解题思路

从题目上可以看到,从n到1有两种路线,如果是偶数,即每次除以2,如果是奇数,则需要找n+1和n-1哪种情况需要的操作次数更小,所以可以自顶向下去搜索,寻找最小操作次数,同时可以打表记录一些已经重复搜索过的值。

根据题意可得需要求将n转为1得最小替换次数,分两种情况

n为偶数,只有一种替换方式 将n转为n/2 n为奇数,有两种替换方式,将n转为n-1或n+1,这两种替换方式需要选择较小的那一种 base case : 当已经转化到1时不需要再转化

使用备忘录来记录已经得到过的值,因为n取值为1<n<=Integer.MAX_VALUE,所以还需要考虑当n=Integer.MAX_VALUE时只有一种转化方式,就是n=n-1,否则超出int范围。

将实际比较的数据单位变成Long 传递过来的值小于或等于1时结果为0 如果传递过来的值已经在map集合中存储了,则直接返回结果。

代码实现

private Map < Integer, Integer > cache;
public int integerReplacement(int n) {
    cache = new HashMap < > ();
    return dfs(n);
}
private int dfs(int n) {
    if (n == 1) {
        return 0;
    }
    if (cache.containsKey(n)) {
        return cache.get(n);
    }
    if ((n & 1) == 1) {
        cache.put(n, Math.min(dfs(n / 2 + 1), dfs(n / 2)) + 2);
    } else {
        cache.put(n, dfs(n / 2) + 1);
    }
    return cache.get(n);
}

运行结果

Snipaste_2023-06-06_22-38-38.png

复杂度分析

  • 空间复杂度:O(1)
  • 时间复杂度:O(n)

掘金(JUEJIN) 一起分享知识, Keep Learning!