159、整数替换

博客围绕给定正整数 n 变为 1 的最小替换次数展开。若 n 为偶数用 n / 2 替换,奇数可用 n + 1 或 n - 1 替换。介绍了示例,提及从 1 到 n 代码会溢出问题,探讨用动态规划、递归和位运算解决,还指出特殊情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
给定一个正整数 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

思考从1–>n但是下面这个代码当非常大时会溢出,这个很头疼…
使用动态规划,即1–>0 2–>1 4 —> 2,因此就可以确定3是2,以此类推
代码:

class Solution {
    public int integerReplacement(int n) {
        if(n == 1){
			return 0;
		}
		if(n == 2){
			return 1;
		}
		Map<Integer, Integer> map = new HashMap<>();
		int time = 0;
		int tem = 1;
		map.put(tem, time);
		if(tem == n){
			return time;
		}
		for (int i = 1; i <= n; i++) {
			if(map.containsKey(i)){
				map.put(i * 2, map.get(i) + 1);
				continue;
			}else {
				map.put(i, Math.min(map.get(i - 1), map.get(i + 1)) + 1);
				map.put(i * 2, map.get(i) + 1);
			}
		}
		return map.get(n);
    }
}

使用递归,你需要固定一个max为2147483647 返回的是32,否则内存同样溢出

class Solution {
    public int integerReplacement(int n) {
//使用递归,2019年7月12日09:18:59
		if(n == 1){
			return 0;
		}
          if(3 == n) return 2;
		    if(2147483647 == n) return 32;
		if((n & 1  )== 0){
			return 1 + integerReplacement(n >> 1);
		}else {
			return 1 + Math.min(integerReplacement(n + 1),integerReplacement(n - 1));
		}
    }
}

本题是属于位运算,因此还是考虑使用位运算来解决
考虑:如果n是偶数,那么就>>1,如果n是奇数,那么-1还是+1取决于,-1或者+1后的数字是偶数之后变成奇数的次数,比如以11B结尾和01B结尾,那么就是要+1,因为11B+1后变成了00B,这样可能除以2的次数就多一些,当然3这个数字除外,有点特殊。
代码:还是同样的问题对于2147483647 同样要返回的是32

class Solution {
    public int integerReplacement(int n) {
        if(n == 1){
			return 0;
		}
		if(3 == n) 
			return 2;
		int count = 0;
		while (n != 1) {
            if(2147483647 == n){
				return 32;
			}
			if((n & 1) == 0){
				n = n >> 1;
    			count ++;
    			continue;
			}
			if(n == 3){
				count += 2;
				break;
			}
			if((n & 3) == 3){
					n ++;
			}else {
					n --;
				}
			count ++;
		}
		return count;
    }
}
### LeetCode 替换整数问题分析 在 LeetCode 平台上,“替换整数”的表述较为宽泛,可能涉及多种类型的题目。为了更好地理解这一类问题,可以考虑以下几个方面: #### 1. 数字操作与转换 对于某些特定的数字处理问题,比如将一个整数的每一位相乘再减去每位数字之和的操作,在 C++ 中可以通过取模运算 `%` 和除法 `/` 来实现对单个位数的操作[^1]。 ```cpp int subtractProductAndSum(int n) { int product = 1; int sum = 0; while (n != 0){ int digit = n % 10; product *= digit; sum += digit; n /= 10; } return product - sum; } ``` 此代码片段展示了如何计算给定整数 `n` 的各个位上的数值相乘的结果以及它们之间的差异。 #### 2. 特殊情况处理 当遇到像 10 或者 100 这样的特殊情况时(即最后一位是零),应当特别注意输出结果是否会受到影响或者是否有特殊的要求[^4]。通常情况下,如果只是简单地求解各位置上非零数字间的算术关系,则不会受到末尾零的影响;但如果涉及到其他逻辑判断,则需额外小心对待这类输入数据。 #### 3. 动态规划应用实例 另一个常见的主题是在一定条件下优化某个目标函数值的问题,例如整数拆分以达到最大乘积的情况。通过动态规划的方法可以在多项式时间内解决此类难题,并且能够有效地找到全局最优解[^3]。 ```python def integerBreak(n: int) -> int: dp = [0]*(n+1) for i in range(2,n+1): curMax = 0 for j in range(1,i//2+1): curMax=max(curMax,max(j*(i-j),j*dp[i-j])) dp[i]=curMax return dp[-1] ``` 上述 Python 实现利用了动态规划的思想来解决问题,其中 `dp[i]` 表示把正整数 `i` 拆分成若干部分后的最大乘积。 #### 4. 序列中的模式识别 还有一类问题是关于查找序列中存在的某种规律或子结构的存在性验证,如寻找是否存在三个严格递增元素构成三元组的情形。这同样属于广义上的“替换”概念之一——通过对原始列表进行适当调整从而满足新的条件约束[^2]。 ```java public class Solution { public boolean increasingTriplet(int[] nums) { int len = nums.length; if(len<3)return false; int numI = Integer.MAX_VALUE; int numJ = Integer.MAX_VALUE; for(int i=0;i<len;i++){ if(nums[i]<=numI)numI = nums[i]; else if(nums[i]<=numJ)numJ = nums[i]; else return true; } return false; } } ``` 这段 Java 代码实现了在一个数组中检测是否存在长度为 3 的上升子序列的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值