列表

详情


2601. 质数减法运算

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

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

如果你能通过上述运算使得 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 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: bool primeSubOperation(vector<int>& nums) { } };

golang 解法, 执行用时: 8 ms, 内存消耗: 4.6 MB, 提交时间: 2023-03-29 14:56:33

var p = []int{0} // 哨兵,避免二分越界

func init() {
	const mx = 1000
	np := [mx]bool{}
	for i := 2; i < mx; i++ {
		if !np[i] {
			p = append(p, i) // 预处理质数列表
			for j := i * i; j < mx; j += i {
				np[j] = true
			}
		}
	}
}

func primeSubOperation(nums []int) bool {
	pre := 0
	for _, x := range nums {
		if x <= pre {
			return false
		}
		pre = x - p[sort.SearchInts(p, x-pre)-1] // 减去 < x-pre 的最大质数
	}
	return true
}

java 解法, 执行用时: 2 ms, 内存消耗: 41.3 MB, 提交时间: 2023-03-29 14:56:12

class Solution {
    private final static int MX = 1000;
    private final static int[] primes = new int[169];

    static {
        var np = new boolean[MX + 1];
        int pi = 1; // primes[0] = 0 避免二分越界
        for (int i = 2; i <= MX; ++i)
            if (!np[i]) {
                primes[pi++] = i; // 预处理质数列表
                for (int j = i; j <= MX / i; ++j)
                    np[i * j] = true;
            }
    }

    public boolean primeSubOperation(int[] nums) {
        int pre = 0;
        for (int x : nums) {
            if (x <= pre) return false;
            int j = lowerBound(primes, x - pre);
            pre = x - primes[j - 1];
        }
        return true;
    }

    // 见 https://www.bilibili.com/video/BV1AP41137w7/
    private int lowerBound(int[] nums, int target) {
        int left = -1, right = nums.length; // 开区间 (left, right)
        while (left + 1 < right) { // 区间不为空
            // 循环不变量:
            // nums[left] < target
            // nums[right] >= target
            int mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid; // 范围缩小到 (mid, right)
            else
                right = mid; // 范围缩小到 (left, mid)
        }
        return right;
    }
}

python3 解法, 执行用时: 48 ms, 内存消耗: 14.9 MB, 提交时间: 2023-03-29 14:54:25

'''
设 pre 是上一个减完后的数字,x = nums[i] 为当前数字。
设 p 是满足 x−p>pre 的最大质数,换言之,p 是小于 x−pre 的最大质数,这可以预处理质数列表后,用二分查找得到。
'''
MX = 1000
P = [0]  # 哨兵,避免二分越界
is_prime = [True] * MX
for i in range(2, MX):
    if is_prime[i]:
        P.append(i)  # 预处理质数列表
        for j in range(i * i, MX, i):
            is_prime[j] = False

class Solution:
    def primeSubOperation(self, nums: List[int]) -> bool:
        pre = 0
        for x in nums:
            if x <= pre: return False
            pre = x - P[bisect_left(P, x - pre) - 1]  # 减去 < x-pre 的最大质数
        return True

上一题