质数减法运算

73 阅读2分钟

2601. 质数减法运算 - 力扣(LeetCode)

给你一个下标从 0 开始的整数数组 nums ,数组长度为 n

你可以执行无限次下述运算:

  • 选择一个之前未选过的下标 i ,并选择一个 严格小于 nums[i] 的质数 p ,从 nums[i] 中减去 p

如果你能通过上述运算使得 nums 成为严格递增数组,则返回 true ;否则返回 false

严格递增数组 中的每个元素都严格大于其前面的元素。

示例 1:

输入: nums = [4,9,6,10]
输出: true
解释:
在第一次运算中:选择 i = 0 和 p = 3 ,然后从 nums[0] 减去 3 ,nums 变为 [1,9,6,10] 。
在第二次运算中:选择 i = 1 和 p = 7 ,然后从 nums[1] 减去 7 ,nums 变为 [1,2,6,10] 。
第二次运算后,nums 按严格递增顺序排序,因此答案为 true 。

示例 2:

输入: nums = [6,8,11,12]
输出: true
解释: nums 从一开始就按严格递增顺序排序,因此不需要执行任何运算。

示例 3:

输入: nums = [5,8,3]
输出: false
解释: 可以证明,执行运算无法使 nums 按严格递增顺序排序,因此答案是 false 。

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000
  • nums.length == n

思路

本题最终结果要严格递增,nums[i] < nums [i + 1], 如果 nums[i] >= nums[i + 1],我们需要从 nums[i] 中减去一个质数,使得 nums[i] < nums[i + 1],为了使 nums[i]前面的数也能满足要求,我们需要使 nums[i] 尽可能的大 ,设 n = nums[i] - nums[i + 1] - 1,我们需要找到大于等于 n 的最小质数,又因为最小的质数是 2n = Math.max(2, n),我们从 n 开始遍历,如果 n 是质数,n 就是我们要求的最小质数,否则 n++,继续判断,直到找到那个质数为止,此时 nums[i] = nums [i] - n。因为 1<= nums [i],切 nums 严格递增,nums[i] 还应该满足 nums[i] > i

我们从后往前遍历 nums,按照上面的思路,如果 nums[i] > nums[i + 1],找到那个最小的质数 n,使 nums[i] -= n,我们再比较 nums[i]是否大于 i,大于 i,接着循环,小于等于 i,退出循环,返回 false。如果最后正常循环完成,返回 true。代码如下。

解题

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var primeSubOperation = function (nums) {
  const isPrime = (n) => {
    if (n <= 3) return true;
    if (n % 2 === 0) return false;
    let i = 3;
    while (i * i <= n) {
      if (n % i === 0) {
        return false;
      }
      i += 2;
    }
    return true;
  };
  for (let i = nums.length - 2; i >= 0; i--) {
    if (nums[i] >= nums[i + 1]) {
      let n = Math.max(2, nums[i] - nums[i + 1] + 1);
      while (!isPrime(n)) {
        n++;
      }
      nums[i] -= n;
    }
    if (nums[i] <= i) {
      return false;
    }
  }
  return true;
};