【C++二分查找】2601. 质数减法运算

本文涉及的基础知识点

C++二分查找
贪心(决策包容性)

LeetCode2601. 质数减法运算

给你一个下标从 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[i1],后修改nums[i2]    ⟺    \iff 先修改nums[i2],后修改nums[i1]
故可以按下标从小到大修改。
贪心:nums[i]在大于nums[i-1]的情况下尽可能的小。可用决策包容性证明。
prime按升序记录1000以内的质数。令nums[i]减少x,则:x <nums[i]
nums[i]-x > nums[i-1] 即 nums[i]-nums[i-1] > x
两者联合 x < min(nums[i],nums[i]-nums[i-1])
即:x < nums[i] - nums[j-1]

代码

核心代码

class CUniqueFactorization
{
public:
	CUniqueFactorization(int iMax) {
		int iMaxSqrt = sqrt(iMax) + 2;
		m_vPrime = CreatePrime(iMaxSqrt);
	}
	void Factorization(int x) {
		m_a.clear();
		m_n.clear();
		for (const auto& iPre : m_vPrime) {
			int cnt = 0;
			while (0 == x % iPre) {
				cnt++;
				x /= iPre;
			}
			if (cnt > 0) {
				m_a.emplace_back(iPre);
				m_n.emplace_back(cnt);
			}
		}
		if (x > 1) {
			m_a.emplace_back(x);
			m_n.emplace_back(1);
		}
	}
	vector<int> m_a, m_n;
	vector<int> CreatePrimeOld(int iMax)
	{
		vector<int> vNo(iMax + 1);
		vector<int> vPrime;
		for (int i = 2; i <= iMax; i++)
		{
			if (!vNo[i])
			{
				vPrime.emplace_back(i);
			}
			for (const auto& n : vPrime)
			{
				if (n * i > iMax)
				{
					break;
				}
				vNo[n * i] = true;
			}
		}
		return vPrime;
	}
	static vector<int> CreatePrime(int iMax)
	{
		vector<bool> isPrime(iMax + 1, true);
		vector<int> vPrime;
		for (int i = 2; i <= iMax; i++)
		{
			if (isPrime[i])
			{
				vPrime.emplace_back(i);
			}
			for (const auto& n : vPrime)
			{
				if (n * i > iMax) { break; }
				isPrime[n * i] = false;
				if (0 == i % n) { break; }
			}
		}
		return vPrime;
	}
	vector<int> m_vPrime;
};

class Solution {
		public:
			bool primeSubOperation(vector<int>& nums) {
				auto v = CUniqueFactorization::CreatePrime(1000);
				int pre = 0;
				for (auto& n : nums) {
					auto it = lower_bound(v.begin(), v.end(), n - pre);
					if (v.begin() != it)
					{//能变小
						n -= *(--it);
					}
					else if( n <= pre ){
						return false;
					}
					pre = n;
				}
				return true;
			}
		};

单元测试

vector<int> nums;
		TEST_METHOD(TestMethod11)
		{
			vector<int> nums = { 4,9,6,10 };
			auto res = Solution().primeSubOperation(nums);
			AssertEx(true, res);
		}
		TEST_METHOD(TestMethod12)
		{
			vector<int> nums = { 6,8,11,12 };
			auto res = Solution().primeSubOperation(nums);
			AssertEx(true, res);
		}
		TEST_METHOD(TestMethod13)
		{
			vector<int> nums = { 5,8,3 };
			auto res = Solution().primeSubOperation(nums);
			AssertEx(false, res);
		}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闻缺陷则喜何志丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值