Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[pull] master from wisdompeak:master #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
pull merged 8 commits into AlgorithmAndLeetCode:master from wisdompeak:master
Oct 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ class Solution {
for (int j=1; j<=n; j++)
{
if (s[i]==t[j])
dp[i][j] = dp[i-1][j] + dp[i-1][j-1];
dp[i][j] = min(LLONG_MAX/2, dp[i-1][j] + dp[i-1][j-1]);
else
dp[i][j] = dp[i-1][j];
//cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
}
return dp[m][n];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using LL = long long;
class Solution {
public:
long long minimumReplacement(vector<int>& nums)
{
LL ret = 0;
for (int i = nums.size()-2; i>=0; i--)
{
LL x = nums[i+1];
LL y = nums[i];
if (y<=x) continue;

if (y%x==0)
{
ret += y/x-1;
nums[i] = x;
}
else
{
int k = y/x+1;
ret += y/x;
nums[i] = y/k;
}
}

return ret;
}
};
5 changes: 5 additions & 0 deletions Greedy/2366.Minimum-Replacements-to-Sort-the-Array/Readme.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
### 2366.Minimum-Replacements-to-Sort-the-Array

#### 解法1

我们从后往前看,对于最后一个数,我们肯定不会拆分。一旦将其拆分的话变小的话,那么前面的数就有更大的概率需要拆得更小。

接着假设最后一个数是x,倒数第二个数是y。如果y小于等于x,那么最后两个元素已经是递增关系,y就不用拆分了,理由同上。如果y大于x,那么就必须拆分y,那么怎么拆分呢?
Expand All @@ -21,3 +23,6 @@ p <= (x-d) / (k+1)
此时这是不是最优的操作呢?并不是。如果`d2 < x2`,其实我们可以将k个x2里面的一部分(而不是整体)拿出1来再贡献给d2,必然可以使得d2再拉至于x2-1平齐的高度。这是因为之前我们知道,如果k个x2每人都再贡献1出来,会导致`d2`会比`x2-1`还大。所以这意味着,如果贡献出部分的1出来,就能让`d2`与`x2-1`持平。在这种情况下,`x2-1`就是拆分出来的k+1份里的最小值。

于是,这个回合结束我们将nums[i]赋值为`x2`(如果`d2==x2`)或者`x2-1`(如果`d2<x2`)。下一个回合就是针对nums[i],来策划对于nums[i-1]的拆分。完全重复上述的过程。

#### 解法2
还有一种写起来更简单的解法。我们已经知道,我们试图将y做最少的拆分,且每一份不能拆过x。显然,我们拆分的份数就是`k = ⌈y/x⌉`,其中`⌈.⌉`表示一个分数的上整界。如果你还知道一个结论(或者直觉):将一个数y拆成k份,一定可以表示成若干个`⌈y/k⌉`与若干个`⌊y/k⌋`之和,那么显然这就是最为平均的一种分法(因为任何元素之间彼此不超过1)。根据解法1的分析,我们会把nums[i]重置为这种分法得到的最大的最小值值`⌊y/k⌋`。
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using LL = long long;
class Solution {
public:
long long makeSimilar(vector<int>& nums, vector<int>& target)
{
vector<LL>odd1, odd2, even1, even2;
for (auto x: nums)
{
if (x%2==0)
even1.push_back(x);
else
odd1.push_back(x);
}
for (auto x: target)
{
if (x%2==0)
even2.push_back(x);
else
odd2.push_back(x);
}

return helper(even1, even2) + helper(odd1, odd2);
}

LL helper(vector<LL>&nums, vector<LL>&target)
{
sort(target.begin(), target.end());
sort(nums.begin(), nums.end());

LL count = 0;
for (int i=0; i<nums.size(); i++)
if (nums[i] > target[i])
count += (nums[i]-target[i])/2;

return count;
}

};
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
### 2449.Minimum-Number-of-Operations-to-Make-Arrays-Similar

很显然题目的意思是,nums经过一系列操作之后,需要变成targets。于是nums和targets的数组元素之和必然相等,否则无法实现+2/-2的守恒。

另外,我们发现,偶数无论如何也无法操作成奇数,反之亦然。所以知道,需要将奇数偶数分开处理,即nums里的奇数需要多少操作转化为targets里的奇数,同理nums里的偶数需要多少操作否转化为targets里的偶数。

接下来,我们考虑只含有奇数的nums数组和只含有奇数的targets数组。很明显,我们必然会把nums[0]转化为targets[0],将nums[1]转化为targets[1],依次类推。这样能使得每对元素差的绝对值之和最小。简单的证明可以从两对开始研究。假设有`nums[i]<nums[j]`和`targets[x]<targets[y]`,那么无非三种情况
1. nums[i]<nums[j]<targets[x]<targets[y]
2. nums[i]<targets[x]<nums[j]<targets[y]
3. nums[i]<targets[x]<targets[y]<nums[j]
画个线段图就发现,无论哪一种,都有`abs(nums[i]-targets[x])+ abs(nums[j]-targets[y]) <= abs(nums[i]-targets[y])+ abs(nums[j]-targets[x])`。将这个结论推广至任意两对元素之间的判断,就可以得出前面的结论。

有了这个策略之后,我们就可以计算出每对元素之间,需要多少次+的操作,或者多少次-的操作。但实际上我们只需要记录+的操作即可,因为题目保证最终全局(即包括了奇数数组和偶数数组)而言+和-的操作一定守恒。
1 change: 1 addition & 0 deletions Readme.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,7 @@
[2365.Task-Scheduler-II](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2365.Task-Scheduler-II) (M)
[2366.Minimum-Replacements-to-Sort-the-Array](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2366.Minimum-Replacements-to-Sort-the-Array) (H-)
[2371.Minimize-Maximum-Value-in-a-Grid](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2371.Minimize-Maximum-Value-in-a-Grid) (M+)
[2449.Minimum-Number-of-Operations-to-Make-Arrays-Similar](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2449.Minimum-Number-of-Operations-to-Make-Arrays-Similar) (M+)
* ``DI Sequence``
[942.DI-String-Match](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/942.DI-String-Match) (M)
[484.Find-Permutation](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/484.Find-Permutation) (M)
Expand Down

AltStyle によって変換されたページ (->オリジナル) /