本文涉及的基础知识点
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++**实现。