diff --git a/Binary_Search/3399.Smallest-Substring-With-Identical-Characters-II/3399.Smallest-Substring-With-Identical-Characters-II.cpp b/Binary_Search/3399.Smallest-Substring-With-Identical-Characters-II/3399.Smallest-Substring-With-Identical-Characters-II.cpp new file mode 100644 index 000000000..5a0c7928d --- /dev/null +++ b/Binary_Search/3399.Smallest-Substring-With-Identical-Characters-II/3399.Smallest-Substring-With-Identical-Characters-II.cpp @@ -0,0 +1,61 @@ +class Solution { +public: + int minLength(string s, int numOps) + { + vectorarr; + vectornums; + for (auto ch: s) nums.push_back(ch-'0'); + + int n = s.size(); + for (int i=0; iarr, vector&nums, int len, int numOps) + { + if (len==1) + { + int count = 0; + for (int i=0; inumOps) + return false; + } + return true; + } +}; diff --git a/Binary_Search/3399.Smallest-Substring-With-Identical-Characters-II/Readme.md b/Binary_Search/3399.Smallest-Substring-With-Identical-Characters-II/Readme.md new file mode 100644 index 000000000..b32e12466 --- /dev/null +++ b/Binary_Search/3399.Smallest-Substring-With-Identical-Characters-II/Readme.md @@ -0,0 +1,18 @@ +### 3399.Smallest-Substring-With-Identical-Characters-II + +容易发现,只要操作次数越多,就越容易将最长的identical-chracter sbustring长度降下来,所以很明显适合二分搜值的框架。 + +于是问题转变成给定一个len,问是否能在numOps次flip操作内,使得s里不存在超过长度len的identical substring。 + +我们将原字符串里进行预处理,分割为一系列由相同字符组成的子串。对于任意一段长度为x的子串,我们至少需要做多少次flip呢?很明显,贪心思想就可以得到最优解,即每隔len个字符,我们就做一次flip。假设最少做t次flip,我们需要满足 +``` +x <= (len+1) * t + len +``` +才能保证x里面不会有超过长度为len的identical substring。于是求得`t>=(x-k)/(k+1)`。不等式右边是小数时,取上界整数。 + +但是此题有一个坑。如果len是1的话,那么当x是偶数时,会给下一段x带来困扰。比如说s=00001111,我们在处理第一段0000时,会得到贪心的做法做两次flip使得其变成0101。我们发现这样的话下一段的1111其实需要处理的长度是5,给算法带来了极大的不便。比较简单的处理方法就是对len=1的情况特别处理,跳出之前的思维模式,只要考虑将s强制转换为01相间的字符串,计算需要做的flip即可。 + +那为什么len是2的时候我们就不用担心呢?距离s=000111,如果按照贪心的做法,对于第一段000我们需要做一次flip使得其变成001,似乎依然会影响到下一段的111. 但事实上,对于一段我们不需要变换成001,可以将最右端的1随意往左调动一下,变换成010。结果就是flip的次数不变的前提下,依然可以保证不会出现长度超过2的identical substring。注意,回顾一下二分搜值的框架,我们不要求一定要构造出长度为2的identical substring。 + +同理当len=3时,也不会出现类似影响下一段的困扰。之前的计算t的表达式依然可以适用。 + diff --git a/Readme.md b/Readme.md index 51776579d..45ed17189 100644 --- a/Readme.md +++ b/Readme.md @@ -147,6 +147,7 @@ [3048.Earliest-Second-to-Mark-Indices-I](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/3048.Earliest-Second-to-Mark-Indices-I) (M+) [3049.Earliest-Second-to-Mark-Indices-II](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/3049.Earliest-Second-to-Mark-Indices-II) (H) [3097.Shortest-Subarray-With-OR-at-Least-K-II](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/3097.Shortest-Subarray-With-OR-at-Least-K-II) (M) +[3399.Smallest-Substring-With-Identical-Characters-II](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/3399.Smallest-Substring-With-Identical-Characters-II) (H-) * ``Find K-th Element`` [215.Kth-Largest-Element-in-an-Array](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/215.Kth-Largest-Element-in-an-Array) (M) [287.Find-the-Duplicate-Number](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/287.Find-the-Duplicate-Number) (H-)

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