<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>medium &#8211; Huahua&#8217;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/medium/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog</link>
	<description></description>
	<lastBuildDate>Sun, 13 Apr 2025 03:01:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.2</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>medium &#8211; Huahua&#8217;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2161. Partition Array According to Given Pivot</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2161-partition-array-according-to-given-pivot/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2161-partition-array-according-to-given-pivot/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 13 Apr 2025 03:01:02 +0000</pubDate>
				<category><![CDATA[Array]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[partition]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10348</guid>

					<description><![CDATA[最直接的方法就是扫描三遍，&#60;, = , > pivot。 时间复杂度：O(n)空间复杂度：O(1) // no extra space used except for output [crayon-67fc7e2852700287204684/]]]></description>
										<content:encoded><![CDATA[
<p>最直接的方法就是扫描三遍，&lt;, = , > pivot。</p>



<p>时间复杂度：O(n)<br>空间复杂度：O(1) // no extra space used except for output</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  vector&lt;int&gt; pivotArray(vector&lt;int&gt;&amp; nums, int pivot) {
    vector&lt;int&gt; ans;
    for (int x: nums)
      if (x &lt; pivot) ans.push_back(x);
    for (int x : nums)
      if (x == pivot) ans.push_back(x);
    for (int x : nums)
      if (x &gt; pivot) ans.push_back(x);
    return ans;
  }
};</pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2161-partition-array-according-to-given-pivot/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2024. Maximize the Confusion of an Exam</title>
		<link>https://zxi.mytechroad.com/blog/sliding-window/leetcode-2024-maximize-the-confusion-of-an-exam/</link>
					<comments>https://zxi.mytechroad.com/blog/sliding-window/leetcode-2024-maximize-the-confusion-of-an-exam/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 12 Apr 2025 17:09:15 +0000</pubDate>
				<category><![CDATA[Sliding Window]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[sliding window]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10343</guid>

					<description><![CDATA[数据规模高达5 *104,我们只能使用O(n)的算法了。 可以想到的就是滑动窗口(sliding window)，由于最长长度未知，我们可以使用动态滑动窗口。 记录当前滑动窗口中T和F出现的次数，如果其中较少的一个&#60;=k，那么就可以全部替换它，使得整个滑动窗口都变成相同的值。如果这个时候滑动窗口长度大于当前最大长度，我们就把滑动窗口变大，右侧+1，并更新最大长度。否则，减少滑动窗口，左侧-1。 时间复杂度：O(n)空间复杂度：O(2) [crayon-67fc7e2852c0a740767141/]]]></description>
										<content:encoded><![CDATA[
<p>数据规模高达5 *10<sup>4</sup>,我们只能使用O(n)的算法了。</p>



<p>可以想到的就是滑动窗口(sliding window)，由于最长长度未知，我们可以使用动态滑动窗口。</p>



<p>记录当前滑动窗口中T和F出现的次数，如果其中较少的一个&lt;=k，那么就可以全部替换它，使得整个滑动窗口都变成相同的值。如果这个时候滑动窗口长度大于当前最大长度，我们就把滑动窗口变大，右侧+1，并更新最大长度。否则，减少滑动窗口，左侧-1。</p>



<p>时间复杂度：O(n)<br>空间复杂度：O(2)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int maxConsecutiveAnswers(string_view A, int k) {
    int ans = 0;
    int f = 0;
    array&lt;int, 2&gt; count; // number of 'F' and 'T' in the sliding window
    for (int i = 0; i &lt; A.size(); ++i) {
      ++count[A[i] == 'T'];
      if (min(count[0], count[1]) &lt;= k &amp;&amp; count[0] + count[1] &gt; ans)
        ++ans;
      else
        --count[A[i - ans] == 'T'];
    }
    return ans;
  }
};</pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/sliding-window/leetcode-2024-maximize-the-confusion-of-an-exam/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2023. Number of Pairs of Strings With Concatenation Equal to Target</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-2023-number-of-pairs-of-strings-with-concatenation-equal-to-target/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-2023-number-of-pairs-of-strings-with-concatenation-equal-to-target/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 11 Apr 2025 16:24:45 +0000</pubDate>
				<category><![CDATA[String]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[string_view]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10337</guid>

					<description><![CDATA[方法1: Brute Force 枚举所有的(nums[i], nums[j])组合，相加在和target比较。 时间复杂度：O(mn2) m为字符串的最长长度。空间复杂度：O(m) 优化前 67ms, 49.3M [crayon-67fc7e2852d96604653914/] 一些工程上的优化 优化后 3ms, 12.88MB [crayon-67fc7e2852d9f004700851/]]]></description>
										<content:encoded><![CDATA[
<p>方法1: Brute Force</p>



<p>枚举所有的(nums[i], nums[j])组合，相加在和target比较。</p>



<p>时间复杂度：O(mn<sup>2</sup>) m为字符串的最长长度。<br>空间复杂度：O(m)</p>



<p>优化前 67ms, 49.3M</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int numOfPairs(vector&lt;string&gt;&amp; nums, string target) {
    const int n = nums.size();
    int ans = 0;
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; n; ++j)
        if (i != j &amp;&amp; nums[i] + nums[j] == target)
          ++ans;
    return ans;
  }
};</pre>



<p>一些工程上的优化</p>



<ul class="wp-block-list">
<li>用string_view作为参数类型，减少一次string copy</li>



<li>先比较长度，再判断内容。</li>



<li>string_view.substr 是O(1)时间，和直接用strncmp比较内容是一样的。</li>
</ul>



<p>优化后 3ms, 12.88MB</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int numOfPairs(vector&lt;string&gt;&amp; nums, string_view target) {
    const int n = nums.size();
    int ans = 0;
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; n; ++j)
        if (i != j 
            &amp;&amp; nums[i].size() + nums[j].size() == target.size()
            &amp;&amp; target.substr(0, nums[i].size()) == nums[i]
            &amp;&amp; target.substr(nums[i].size()) == nums[j])
              ++ans;
    return ans;
  }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/string/leetcode-2023-number-of-pairs-of-strings-with-concatenation-equal-to-target/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2012. Sum of Beauty in the Array</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2012-sum-of-beauty-in-the-array/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2012-sum-of-beauty-in-the-array/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 11 Apr 2025 04:21:38 +0000</pubDate>
				<category><![CDATA[Array]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[prefix max]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10326</guid>

					<description><![CDATA[数据规模比较大，算法必须是O(n)的。 可以预先使用O(n)时间计算nums[0] .. nums[i]的最大值，存在left[i]中，以及nums[i] .. nums[n-1]的最小值存在right[i]中。然后再按题目的定义计算即可。 时间复杂度：O(n)空间复杂度：O(n) [crayon-67fc7e2852f4d427948641/]]]></description>
										<content:encoded><![CDATA[
<p>数据规模比较大，算法必须是O(n)的。</p>



<p>可以预先使用O(n)时间计算nums[0] .. nums[i]的最大值，存在left[i]中，以及nums[i] .. nums[n-1]的最小值存在right[i]中。然后再按题目的定义计算即可。</p>



<p>时间复杂度：O(n)<br>空间复杂度：O(n)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int sumOfBeauties(vector&lt;int&gt;&amp; nums) {
    const int n = nums.size();
    vector&lt;int&gt; left(n, nums[0]);
    vector&lt;int&gt; right(n, nums.back());
    for (int i = 1; i &lt; n; ++i)
      left[i] = max(left[i - 1], nums[i]);
    for (int i = n - 2; i &gt;= 0; --i)
      right[i] = min(right[i + 1], nums[i]);
    int ans = 0;
    for (int i = 1; i &lt; n - 1; ++i)
      if (left[i - 1] &lt; nums[i] &amp;&amp; nums[i] &lt; right[i + 1])
        ans += 2;
      else if (nums[i - 1] &lt; nums[i] &amp;&amp; nums[i] &lt; nums[i + 1])
        ans += 1;
    return ans;
  }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2012-sum-of-beauty-in-the-array/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1992. Find All Groups of Farmland</title>
		<link>https://zxi.mytechroad.com/blog/simulation/leetcode-1992-find-all-groups-of-farmland/</link>
					<comments>https://zxi.mytechroad.com/blog/simulation/leetcode-1992-find-all-groups-of-farmland/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 11 Apr 2025 03:34:14 +0000</pubDate>
				<category><![CDATA[Simulation]]></category>
		<category><![CDATA[grid]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[simulation]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10315</guid>

					<description><![CDATA[已经告诉你所有的农田都是规整的矩形，题目难度一下子降低了。对于每一个农田的左上角，找到它的宽度和高度即可。然后把整个农田矩形标记为林地/非农田即可。 时间复杂度：O(m*n) 每个格子最多遍历3遍。空间复杂度：O(1) [crayon-67fc7e28530a5891452523/]]]></description>
										<content:encoded><![CDATA[
<p>已经告诉你所有的农田都是规整的矩形，题目难度一下子降低了。<br>对于每一个农田的左上角，找到它的宽度和高度即可。<br>然后把整个农田矩形标记为林地/非农田即可。</p>



<p>时间复杂度：O(m*n) 每个格子最多遍历3遍。<br>空间复杂度：O(1)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  vector&lt;vector&lt;int&gt;&gt; findFarmland(vector&lt;vector&lt;int&gt;&gt;&amp; land) {
    const int m = land.size();
    const int n = land[0].size();
    vector&lt;vector&lt;int&gt;&gt; ans;
    for (int i = 0; i &lt; m; ++i)
      for (int j = 0; j &lt; n; ++j) {
        if (!land[i][j]) continue;
        int w = 0;
        int h = 0;
        while (j + w &lt; n &amp;&amp; land[i][j + w]) ++w;
        while (i + h &lt; m &amp;&amp; land[i + h][j]) ++h;
        ans.push_back({i, j, i + h - 1, j + w - 1});
        for (int p = 0; p &lt; h; ++p)
          for (int q = 0; q &lt; w; ++q)
            land[i + p][j + q] = 0; // mark as seen.
      }
    return ans;
  }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/simulation/leetcode-1992-find-all-groups-of-farmland/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 646. Maximum Length of Pair Chain</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-646-maximum-length-of-pair-chain/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-646-maximum-length-of-pair-chain/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 10 Apr 2025 05:25:42 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Greedy]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[greedy]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[proof]]></category>
		<category><![CDATA[subset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10301</guid>

					<description><![CDATA[这题我选DP，因为不需要证明，直接干就行了。 方法1: DP 首先还是需要对pairs的right进行排序。一方面是为了方便chaining，另一方面是可以去重。 然后定义 dp[i] := 以pairs[i]作为结尾，最长的序列的长度。 状态转移：dp[i] = max(dp[j] + 1) where pairs[i].left > pairs[j].right and 0 &#60; j &#60; i. 解释：对于pairs[i]，找一个最优的pairs[j]，满足pairs[i].left >&#8230;]]></description>
										<content:encoded><![CDATA[
<p>这题我选DP，因为不需要证明，直接干就行了。</p>



<p>方法1: DP</p>



<p>首先还是需要对pairs的right进行排序。一方面是为了方便chaining，另一方面是可以去重。</p>



<p>然后定义 dp[i] := 以pairs[i]作为结尾，最长的序列的长度。<br><br>状态转移：dp[i] = max(dp[j] + 1) where pairs[i].left > pairs[j].right and 0 &lt; j &lt; i.</p>



<p>解释：对于pairs[i]，找一个最优的pairs[j]，满足pairs[i].left > pairs[j].right，这样我就可以把pairs[i]追加到以pairs[j]结尾的最长序列后面了，长度+1。</p>



<p>边检条件：dp[0:n] = 1，每个pair以自己作为序列的最后元素，长度为1。</p>



<p>时间复杂度：O(n<sup>2</sup>)<br>空间复杂度：O(n)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int findLongestChain(vector&lt;vector&lt;int&gt;&gt;&amp; pairs) {
    sort(begin(pairs), end(pairs), [](const auto&amp; p1, const auto&amp; p2){
      return p1[1] &lt; p2[1];
    });

    const int n = pairs.size();

    vector&lt;int&gt; dp(n, 1);
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; i; ++j)
        if (pairs[i][0] &gt; pairs[j][1])
          dp[i] = max(dp[i], dp[j] + 1);

    return *max_element(begin(dp), end(dp));
  }
};</pre>



<p>方法2: 贪心</p>



<p>和DP一样，对数据进行排序。</p>



<p>每当我看到 cur.left > prev.right，那么就直接把cur接在prev后面。我们需要证明这么做是最优的，而不是跳过它选后面的元素。<br><br>Case 0: cur已经是最后一个元素了，跳过就不是最优解了。<br><br>假设cur后面有next, 因为已经排序过了，我们可以得知 next.right >= cur.right。<br><br>Case 1: next.right == cur.right。这时候选cur和选next对后面的决策来说是一样的，但由于Case 0的存在，我必须选cur。<br><br>Case 2: next.right > cur.right。不管left的情况怎么样，由于right更小，这时候选择cur一定是优于next。</p>



<p>综上所述，看到有元素可以连接起来就贪心的选它就对了。</p>



<p>时间复杂度：O(nlogn)<br>空间复杂度：O(1)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int findLongestChain(vector&lt;vector&lt;int&gt;&gt;&amp; pairs) {
    sort(begin(pairs), end(pairs), [](const auto&amp; p1, const auto&amp; p2){
      return p1[1] &lt; p2[1];
    });

    int right = INT_MIN;
    int ans = 0;
    for (const auto&amp; p : pairs)
      if (p[0] &gt; right) {
        right = p[1];
        ++ans;
      }
    return ans;
  }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-646-maximum-length-of-pair-chain/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2349. Design a Number Container System</title>
		<link>https://zxi.mytechroad.com/blog/desgin/leetcode-2349-design-a-number-container-system/</link>
					<comments>https://zxi.mytechroad.com/blog/desgin/leetcode-2349-design-a-number-container-system/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 30 Mar 2025 15:16:49 +0000</pubDate>
				<category><![CDATA[Desgin]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[treeset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10244</guid>

					<description><![CDATA[两个hashtable，一个是index->number，另外一个是number -> {index}，使用treeset，自动排序。 时间复杂度：change O(logn)，find O(1)空间复杂度：O(n) [crayon-67fc7e285347c116968086/]]]></description>
										<content:encoded><![CDATA[
<p>两个hashtable，一个是index->number，另外一个是number -> {index}，使用treeset，自动排序。</p>



<p>时间复杂度：change O(logn)，find O(1)<br>空间复杂度：O(n)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class NumberContainers {
public:
  NumberContainers() {}
  
  void change(int index, int number) {
    if (m_.count(index)) {
      auto it = idx_.find(m_[index]);
      it-&gt;second.erase(index);
      if (it-&gt;second.empty())
        idx_.erase(it);
    }
    m_[index] = number;
    idx_[number].insert(index);
  }
  
  int find(int number) {
    auto it = idx_.find(number);
    if (it == end(idx_)) return -1;
    return *begin(it-&gt;second);
  }
private:
  unordered_map&lt;int, int&gt; m_; // index -&gt; num
  unordered_map&lt;int, set&lt;int&gt;&gt; idx_; // num -&gt; {index}
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/desgin/leetcode-2349-design-a-number-container-system/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 3408. Design Task Manager</title>
		<link>https://zxi.mytechroad.com/blog/priority-queue/leetcode-3408-design-task-manager/</link>
					<comments>https://zxi.mytechroad.com/blog/priority-queue/leetcode-3408-design-task-manager/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 28 Mar 2025 03:45:03 +0000</pubDate>
				<category><![CDATA[Priority Queue]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[iterator]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[priority queue]]></category>
		<category><![CDATA[treemap]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10229</guid>

					<description><![CDATA[pq_ 使用std::map充当优先队列，存储(priority, taskId) -> userId m_ 使用std::unordered_map，存储taskId -> pq_的迭代器 所有操作都是O(logn) [crayon-67fc7e2853d57094841278/]]]></description>
										<content:encoded><![CDATA[
<ol class="wp-block-list"><li>pq_ 使用std::map充当优先队列，存储(priority, taskId) -> userId</li><li>m_ 使用std::unordered_map，存储taskId -> pq_的迭代器</li></ol>



<p>所有操作都是O(logn)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class TaskManager {
public:
    TaskManager(vector&lt;vector&lt;int&gt;&gt;&amp; tasks) {
      for (const auto&amp; task : tasks)
        add(task[0], task[1], task[2]);
    }

    void add(int userId, int taskId, int priority) {
      m_[taskId] = pq_.emplace(make_pair(priority, taskId), userId).first;
    }
    
    void edit(int taskId, int newPriority) {
      const int userId = m_[taskId]-&gt;second;
      rmv(taskId);
      add(userId, taskId, newPriority);
    }
    
    void rmv(int taskId) {
      auto it = m_.find(taskId);
      pq_.erase(it-&gt;second);
      m_.erase(it);
    }
    
    int execTop() {
      if (pq_.empty()) return -1;
      auto it = pq_.rbegin();
      const int userId = it-&gt;second;
      const int taskId = (it-&gt;first.second);
      rmv(taskId);
      return userId;
    }
  private:
    map&lt;std::pair&lt;int,int&gt;, int&gt; pq_; // (priority, taskId) -&gt; userId;
    unordered_map&lt;int, map&lt;std::pair&lt;int,int&gt;, int&gt;::iterator&gt; m_; // taskId -&gt; pq iterator
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/priority-queue/leetcode-3408-design-task-manager/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 3489. Zero Array Transformation IV</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-3489-zero-array-transformation-iv/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-3489-zero-array-transformation-iv/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 16 Mar 2025 14:23:47 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[leetcode]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10211</guid>

					<description><![CDATA[一道不错的DP题目！ 首先看到每次可以取任意一个nums[l] ~ nums[r]的子集 不能用贪心（无法找到全局最优解） 不能用搜索 （数据规模太大，(2^10) ^ 1000） 那只能用动态规划了 状态定义: dp[k][i][j] 能否通过使用前k个变换使得第i个数的值变成j 边界条件: dp[0][i][nums[i]] = 1，不使用任何变换，第i个数可以达到的数值就是nums[i]本身。 状态转移：dp[k][i][j] = dp[k-1][i][j] &#124; (dp[k &#8211; 1][i][j +&#8230;]]></description>
										<content:encoded><![CDATA[
<p>一道不错的DP题目！</p>



<p>首先看到每次可以取任意一个nums[l] ~ nums[r]的子集 </p>



<ul class="wp-block-list"><li>不能用贪心（无法找到全局最优解）</li><li>不能用搜索 （数据规模太大，(2^10) ^ 1000）</li></ul>



<p>那只能用动态规划了</p>



<p>状态定义: dp[k][i][j] 能否通过使用前k个变换使得第i个数的值变成j</p>



<p>边界条件: dp[0][i][nums[i]] = 1，不使用任何变换，第i个数可以达到的数值就是nums[i]本身。</p>



<p>状态转移：dp[k][i][j] = dp[k-1][i][j] | (dp[k &#8211; 1][i][j + val[k]] if l[k] &lt;= i &lt;= r[k] else 0)</p>



<p>简单来说如果第k-1轮第i个数可以变成j + val[k]，那么第k轮就可以通过减去val[k]变成j。</p>



<p>上面是拉的公式，我们也可以写成推的:</p>



<p>dp[k][i][j &#8211; val[k]] = dp[k-1][i][j &#8211; vak[k]] | (dp[k &#8211; 1][i][j] if l[k] &lt;= i &lt;= r[k] else 0)</p>



<p>当然这么定义的话空间复杂度太高O(10^7)，由于第k轮的初始状态就等于k-1轮的状态，我们可以使用滚动数组来降维，空间复杂度降低到O(10^4)。</p>



<p>时间复杂度：O(k*n*MaxV) = O(10^7)。</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
    int minZeroArray(vector&lt;int&gt;&amp; nums, vector&lt;vector&lt;int&gt;&gt;&amp; queries) {
      if (accumulate(begin(nums), end(nums), 0) == 0) return 0;
      constexpr int kMaxV = 1000;
      const int n = nums.size();
      const int K = queries.size();
      vector&lt;bitset&lt;kMaxV + 1&gt;&gt; dp(n);
      for (int i = 0; i &lt; n; ++i)
        dp[i][nums[i]] = 1;
      for (int k = 0; k &lt; K; ++k) {
        int l = queries[k][0];
        int r = queries[k][1];
        int v = queries[k][2];
        for (int i = l; i &lt;= r; ++i)
          for (int j = 0; j &lt;= kMaxV - v; ++j)
            if (dp[i][j + v]) dp[i][j] = 1;
        bool found = true;
        for (int i = 0; i &lt; n; ++i)
          if (!dp[i][0]) found = false;
        if (found) return k + 1;
      }
      return -1;
    }
};</pre>



<p>剪枝优化</p>



<p>上面我们把整个数组看作一个整体，一轮一轮来做。但如果某些数在第k轮能到变成0了，就没有必要参与后面的变化了，或者说它用于无法变成0，那么就是无解，其他数也就不需要再计算了。</p>



<p>所以，我们可以对<strong><em>每个数单独进行dp</em></strong>。即对于第i个数，计算最少需要多少轮才能把它变成0。然后对所有的轮数取一个最大值。总的时间复杂度不变（最坏情况所有数都需要经过K轮）。空间复杂度则可以再降低一个纬度到O(MaxV) = O(10^3)。</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
    int minZeroArray(vector&lt;int&gt;&amp; nums, vector&lt;vector&lt;int&gt;&gt;&amp; queries) {
      constexpr int kMaxV = 1000;
      const int n = nums.size();
      const int K = queries.size();
      auto rounds = [&amp;](int i) -&gt; int {
        if (!nums[i]) return 0;
        bitset&lt;kMaxV + 1&gt; dp;
        dp[nums[i]] = 1;
        for (int k = 0; k &lt; K; ++k) {
          int l = queries[k][0];
          int r = queries[k][1];
          int v = queries[k][2];
          if (l &gt; i || r &lt; i) continue;
          for (int j = 0; j &lt;= kMaxV - v; ++j)
            if (dp[j + v]) dp[j] = 1;
          if (dp[0]) return k + 1;
        }
        return INT_MAX;
      };
      int ans = 0;
      for (int i = 0; i &lt; n &amp;&amp; ans &lt;= K; ++i)
        ans = max(ans, rounds(i));
      return ans == INT_MAX ? -1 : ans;
    }
};</pre>



<p>再加速：我们可以使用C++ bitset的右移操作符，dp &gt;&gt; v，相当于把整个集合全部剪去v，再和原先的状态做或运算（集合并）来达到新的状态。时间复杂度应该是一样的，只是代码简单，速度也会快不少。注: dp&gt;&gt;v 会创建一个临时对象，大小为O(MaxV)。</p>



<p>举个例子：<br>dp = {2, 3, 7} <br>dp &gt;&gt; 2 -&gt; {0, 1, 5}<br>dp |= dp &gt;&gt; v -&gt; {0, 1, 2, 3, 5, 7]</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
    int minZeroArray(vector&lt;int&gt;&amp; nums, vector&lt;vector&lt;int&gt;&gt;&amp; queries) {
      constexpr int kMaxV = 1000;
      const int n = nums.size();
      const int K = queries.size();
      auto rounds = [&amp;](int i) -&gt; int {
        if (!nums[i]) return 0;
        bitset&lt;kMaxV + 1&gt; dp;
        dp[nums[i]] = 1;
        for (int k = 0; k &lt; K; ++k) {
          int l = queries[k][0];
          int r = queries[k][1];
          int v = queries[k][2];
          if (l &gt; i || r &lt; i) continue;
          dp |= dp &gt;&gt; v; // magic
          if (dp[0]) return k + 1;
        }
        return INT_MAX;
      };
      int ans = 0;
      for (int i = 0; i &lt; n &amp;&amp; ans &lt;= K; ++i)
        ans = max(ans, rounds(i));
      return ans == INT_MAX ? -1 : ans;
    }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-3489-zero-array-transformation-iv/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 3319. K-th Largest Perfect Subtree Size in Binary Tree</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-3319-k-th-largest-perfect-subtree-size-in-binary-tree/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-3319-k-th-largest-perfect-subtree-size-in-binary-tree/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 13 Oct 2024 05:02:58 +0000</pubDate>
				<category><![CDATA[Tree]]></category>
		<category><![CDATA[binary tree]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[perfect tree]]></category>
		<category><![CDATA[tree]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10188</guid>

					<description><![CDATA[You are given the&#160;root&#160;of a&#160;binary tree&#160;and an integer&#160;k. Return an integer denoting the size of the&#160;kth&#160;largest&#160;perfect binary&#160; subtree, or&#160;-1&#160;if it doesn&#8217;t exist. A&#160;perfect binary tree&#160;is&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given the&nbsp;<code>root</code>&nbsp;of a&nbsp;<strong>binary tree</strong>&nbsp;and an integer&nbsp;<code>k</code>.</p>



<p>Return an integer denoting the size of the&nbsp;<code>k<sup>th</sup></code>&nbsp;<strong>largest<em>&nbsp;</em>perfect binary</strong><em>&nbsp;</em></p>



<p>subtree, or&nbsp;<code>-1</code>&nbsp;if it doesn&#8217;t exist.</p>



<p>A&nbsp;<strong>perfect binary tree</strong>&nbsp;is a tree where all leaves are on the same level, and every parent has two children.</p>



<p><strong>Example 1:</strong></p>



<p><strong>Input:</strong>&nbsp;root = [5,3,6,5,2,5,7,1,8,null,null,6,8], k = 2</p>



<p><strong>Output:</strong>&nbsp;3</p>



<p><strong>Explanation:</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2024/06/21/image.jpg" alt=""/></figure>



<p>The roots of the perfect binary subtrees are highlighted in black. Their sizes, in decreasing order are&nbsp;<code>[3, 3, 1, 1, 1, 1, 1, 1]</code>.<br>The&nbsp;<code>2<sup>nd</sup></code>&nbsp;largest size is 3.</p>



<p><strong>Example 2:</strong></p>



<p><strong>Input:</strong>&nbsp;root = [1,2,3,4,5,6,7], k = 1</p>



<p><strong>Output:</strong>&nbsp;7</p>



<p><strong>Explanation:</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2024/06/21/image1.jpg" alt=""/></figure>



<p>The sizes of the perfect binary subtrees in decreasing order are&nbsp;<code>[7, 3, 3, 1, 1, 1, 1]</code>. The size of the largest perfect binary subtree is 7.</p>



<p><strong>Example 3:</strong></p>



<p><strong>Input:</strong>&nbsp;root = [1,2,3,null,4], k = 3</p>



<p><strong>Output:</strong>&nbsp;-1</p>



<p><strong>Explanation:</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2024/06/21/image4.jpg" alt=""/></figure>



<p>The sizes of the perfect binary subtrees in decreasing order are&nbsp;<code>[1, 1]</code>. There are fewer than 3 perfect binary subtrees.</p>



<p><strong>Constraints:</strong></p>



<ul class="wp-block-list"><li>The number of nodes in the tree is in the range <code>[1, 2000]</code>.</li><li><code>1 &lt;= Node.val &lt;= 2000</code></li><li><code>1 &lt;= k &lt;= 1024</code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: DFS</strong></h2>



<p>Write a function f() to return the perfect subtree size at node n.</p>



<p>def f(TreeNode n):<br>  if not n: return 0<br>  l, r = f(n.left), f(n.right)<br>  return l + r + 1 if l == r &amp;&amp; l != -1 else -1</p>



<p>Time complexity: O(n + KlogK)<br>Space complexity: O(n)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int kthLargestPerfectSubtree(TreeNode* root, int k) {
    vector&amp;lt;int&gt; ss;
    function&amp;lt;int(TreeNode*)&gt; PerfectSubtree = &amp;#91;&amp;amp;](TreeNode* node) -&gt; int {
      if (node == nullptr) return 0;
      int l = PerfectSubtree(node-&gt;left);
      int r = PerfectSubtree(node-&gt;right);
      if (l == r &amp;amp;&amp;amp; l != -1) {
        ss.push_back(l + r + 1);
        return ss.back();
      }
      return -1;  
    };
    PerfectSubtree(root);
    sort(rbegin(ss), rend(ss));
    return k &amp;lt;= ss.size() ? ss&amp;#91;k - 1] : -1;
  }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-3319-k-th-largest-perfect-subtree-size-in-binary-tree/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 3029. Minimum Time to Revert Word to Initial State I</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-3029-minimum-time-to-revert-word-to-initial-state-i/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-3029-minimum-time-to-revert-word-to-initial-state-i/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 06 Feb 2024 02:02:17 +0000</pubDate>
				<category><![CDATA[String]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[surffix]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10114</guid>

					<description><![CDATA[You are given a&#160;0-indexed&#160;string&#160;word&#160;and an integer&#160;k. At every second, you must perform the following operations: Remove the first&#160;k&#160;characters of&#160;word. Add any&#160;k&#160;characters to the end of&#160;word.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;string&nbsp;<code>word</code>&nbsp;and an integer&nbsp;<code>k</code>.</p>



<p>At every second, you must perform the following operations:</p>



<ul class="wp-block-list"><li>Remove the first&nbsp;<code>k</code>&nbsp;characters of&nbsp;<code>word</code>.</li><li>Add any&nbsp;<code>k</code>&nbsp;characters to the end of&nbsp;<code>word</code>.</li></ul>



<p><strong>Note</strong>&nbsp;that you do not necessarily need to add the same characters that you removed. However, you must perform&nbsp;<strong>both</strong>&nbsp;operations at every second.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>minimum</strong>&nbsp;time greater than zero required for</em>&nbsp;<code>word</code>&nbsp;<em>to revert to its&nbsp;<strong>initial</strong>&nbsp;state</em>.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> word = "abacaba", k = 3
<strong>Output:</strong> 2
<strong>Explanation:</strong> At the 1st second, we remove characters "aba" from the prefix of word, and add characters "bac" to the end of word. Thus, word becomes equal to "cababac".
At the 2nd second, we remove characters "cab" from the prefix of word, and add "aba" to the end of word. Thus, word becomes equal to "abacaba" and reverts to its initial state.
It can be shown that 2 seconds is the minimum time greater than zero required for word to revert to its initial state.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> word = "abacaba", k = 4
<strong>Output:</strong> 1
<strong>Explanation:</strong> At the 1st second, we remove characters "abac" from the prefix of word, and add characters "caba" to the end of word. Thus, word becomes equal to "abacaba" and reverts to its initial state.
It can be shown that 1 second is the minimum time greater than zero required for word to revert to its initial state.
</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> word = "abcbabcd", k = 2
<strong>Output:</strong> 4
<strong>Explanation:</strong> At every second, we will remove the first 2 characters of word, and add the same characters to the end of word.
After 4 seconds, word becomes equal to "abcbabcd" and reverts to its initial state.
It can be shown that 4 seconds is the minimum time greater than zero required for word to revert to its initial state.
</pre>



<p><strong>Constraints:</strong></p>



<ul class="wp-block-list"><li><code>1 &lt;= word.length &lt;= 50</code></li><li><code>1 &lt;= k &lt;= word.length</code></li><li><code>word</code>&nbsp;consists only of lowercase English letters.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: Suffix ==? Prefix</strong></h2>



<p>Compare the suffix with prefix.</p>



<p>word = &#8220;abacaba&#8221;, k = 3<br>ans = 1, &#8220;<s>aba</s>caba&#8221; != &#8220;abac<s>aba</s>&#8220;<br>ans = 2, &#8220;<s>abacab</s>a&#8221; == &#8220;a<s>bacaba</s>&#8220;, we find it.</p>



<p>Time complexity: O(n * n / k)<br>Space complexity: O(1)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int minimumTimeToInitialState(string_view word, int k) {
    const int n = word.length();
    for (int i = 1; i * k &lt; n; ++i) {
      string_view t = word.substr(i * k);
      if (t == word.substr(0, t.length())) return i;
    }      
    return (n + k - 1) / k;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/string/leetcode-3029-minimum-time-to-revert-word-to-initial-state-i/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2976. Minimum Cost to Convert String I</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-2976-minimum-cost-to-convert-string-i/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-2976-minimum-cost-to-convert-string-i/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 08 Jan 2024 14:01:15 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[shortest path]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10100</guid>

					<description><![CDATA[You are given two&#160;0-indexed&#160;strings&#160;source&#160;and&#160;target, both of length&#160;n&#160;and consisting of&#160;lowercase&#160;English letters. You are also given two&#160;0-indexed&#160;character arrays&#160;original&#160;and&#160;changed, and an integer array&#160;cost, where&#160;cost[i]&#160;represents the cost of changing&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given two&nbsp;<strong>0-indexed</strong>&nbsp;strings&nbsp;<code>source</code>&nbsp;and&nbsp;<code>target</code>, both of length&nbsp;<code>n</code>&nbsp;and consisting of&nbsp;<strong>lowercase</strong>&nbsp;English letters. You are also given two&nbsp;<strong>0-indexed</strong>&nbsp;character arrays&nbsp;<code>original</code>&nbsp;and&nbsp;<code>changed</code>, and an integer array&nbsp;<code>cost</code>, where&nbsp;<code>cost[i]</code>&nbsp;represents the cost of changing the character&nbsp;<code>original[i]</code>&nbsp;to the character&nbsp;<code>changed[i]</code>.</p>



<p>You start with the string&nbsp;<code>source</code>. In one operation, you can pick a character&nbsp;<code>x</code>&nbsp;from the string and change it to the character&nbsp;<code>y</code>&nbsp;at a cost of&nbsp;<code>z</code>&nbsp;<strong>if</strong>&nbsp;there exists&nbsp;<strong>any</strong>&nbsp;index&nbsp;<code>j</code>&nbsp;such that&nbsp;<code>cost[j] == z</code>,&nbsp;<code>original[j] == x</code>, and&nbsp;<code>changed[j] == y</code>.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>minimum</strong>&nbsp;cost to convert the string&nbsp;</em><code>source</code><em>&nbsp;to the string&nbsp;</em><code>target</code><em>&nbsp;using&nbsp;<strong>any</strong>&nbsp;number of operations. If it is impossible to convert</em>&nbsp;<code>source</code>&nbsp;<em>to</em>&nbsp;<code>target</code>,&nbsp;<em>return</em>&nbsp;<code>-1</code>.</p>



<p><strong>Note</strong>&nbsp;that there may exist indices&nbsp;<code>i</code>,&nbsp;<code>j</code>&nbsp;such that&nbsp;<code>original[j] == original[i]</code>&nbsp;and&nbsp;<code>changed[j] == changed[i]</code>.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> source = "abcd", target = "acbe", original = ["a","b","c","c","e","d"], changed = ["b","c","b","e","b","e"], cost = [2,5,5,1,2,20]
<strong>Output:</strong> 28
<strong>Explanation:</strong> To convert the string "abcd" to string "acbe":
- Change value at index 1 from 'b' to 'c' at a cost of 5.
- Change value at index 2 from 'c' to 'e' at a cost of 1.
- Change value at index 2 from 'e' to 'b' at a cost of 2.
- Change value at index 3 from 'd' to 'e' at a cost of 20.
The total cost incurred is 5 + 1 + 2 + 20 = 28.
It can be shown that this is the minimum possible cost.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> source = "aaaa", target = "bbbb", original = ["a","c"], changed = ["c","b"], cost = [1,2]
<strong>Output:</strong> 12
<strong>Explanation:</strong> To change the character 'a' to 'b' change the character 'a' to 'c' at a cost of 1, followed by changing the character 'c' to 'b' at a cost of 2, for a total cost of 1 + 2 = 3. To change all occurrences of 'a' to 'b', a total cost of 3 * 4 = 12 is incurred.
</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> source = "abcd", target = "abce", original = ["a"], changed = ["e"], cost = [10000]
<strong>Output:</strong> -1
<strong>Explanation:</strong> It is impossible to convert source to target because the value at index 3 cannot be changed from 'd' to 'e'.
</pre>



<p><strong>Constraints:</strong></p>



<ul class="wp-block-list"><li><code>1 &lt;= source.length == target.length &lt;= 10<sup>5</sup></code></li><li><code>source</code>,&nbsp;<code>target</code>&nbsp;consist of lowercase English letters.</li><li><code>1 &lt;= cost.length == original.length == changed.length &lt;= 2000</code></li><li><code>original[i]</code>,&nbsp;<code>changed[i]</code>&nbsp;are lowercase English letters.</li><li><code>1 &lt;= cost[i] &lt;= 10<sup>6</sup></code></li><li><code>original[i] != changed[i]</code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: All pairs shortest path</strong></h2>



<p>Compute the shortest path (min cost) for any given letter pairs.</p>



<p>Time complexity: O(26^3 + m + n)<br>Space complexity: O(26^2)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
    long long minimumCost(string s, string t, vector&lt;char&gt;&amp; o, vector&lt;char&gt;&amp; c, vector&lt;int&gt;&amp; cost) {
    const int n = c.size();
    vector&lt;vector&lt;int&gt;&gt; d(26, vector&lt;int&gt;(26, 1e9));
    for (int i = 0; i &lt; 26; ++i)
      d[i][i] = 0;
    for (int i = 0; i &lt; n; ++i)
      d[o[i] - 'a'][c[i] - 'a'] = min(d[o[i] - 'a'][c[i] - 'a'], cost[i]);
    for (int k = 0; k &lt; 26; ++k)
      for (int i = 0; i &lt; 26;++i)
        for (int j = 0; j &lt; 26; ++j)
          if (d[i][k] + d[k][j] &lt; d[i][j])
            d[i][j] = d[i][k] + d[k][j];
    long ans = 0;
    for (int i = 0; i &lt; s.size(); ++i) {
      if (d[s[i] - 'a'][t[i] - 'a'] &gt;= 1e9) return -1; 
      ans += d[s[i] - 'a'][t[i] - 'a'];
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-2976-minimum-cost-to-convert-string-i/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2829. Determine the Minimum Sum of a k-avoiding Array</title>
		<link>https://zxi.mytechroad.com/blog/greedy/leetcode-2829-determine-the-minimum-sum-of-a-k-avoiding-array/</link>
					<comments>https://zxi.mytechroad.com/blog/greedy/leetcode-2829-determine-the-minimum-sum-of-a-k-avoiding-array/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 26 Aug 2023 16:40:51 +0000</pubDate>
				<category><![CDATA[Greedy]]></category>
		<category><![CDATA[greedy]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10085</guid>

					<description><![CDATA[You are given two integers,&#160;n&#160;and&#160;k. An array of&#160;distinct&#160;positive integers is called a&#160;k-avoiding&#160;array if there does not exist any pair of distinct elements that sum to&#160;k.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given two integers,&nbsp;<code>n</code>&nbsp;and&nbsp;<code>k</code>.</p>



<p>An array of&nbsp;<strong>distinct</strong>&nbsp;positive integers is called a&nbsp;<strong>k-avoiding</strong>&nbsp;array if there does not exist any pair of distinct elements that sum to&nbsp;<code>k</code>.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>minimum</strong>&nbsp;possible sum of a k-avoiding array of length&nbsp;</em><code>n</code>.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 5, k = 4
<strong>Output:</strong> 18
<strong>Explanation:</strong> Consider the k-avoiding array [1,2,4,5,6], which has a sum of 18.
It can be proven that there is no k-avoiding array with a sum less than 18.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 2, k = 6
<strong>Output:</strong> 3
<strong>Explanation:</strong> We can construct the array [1,2], which has a sum of 3.
It can be proven that there is no k-avoiding array with a sum less than 3.
</pre>



<p><strong>Constraints:</strong></p>



<ul class="wp-block-list"><li><code>1 &lt;= n, k &lt;= 50</code></li></ul>



<h2 class="wp-block-heading"><strong>Solution 1: Greedy + HashTable</strong></h2>



<p>Always choose the smallest possible number starting from 1.</p>



<p>Add all chosen numbers into a hashtable. For a new candidate i, check whether k &#8211; i is already in the hashtable.</p>



<p>Time complexity: O(n)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  int minimumSum(int n, int k) {    
    int sum = 0;
    unordered_set&lt;int&gt; s;
    for (int i = 1; s.size() != n; ++i) {
      if (s.count(k - i)) continue;
      sum += i;
      s.insert(i);
    }
    return sum;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/greedy/leetcode-2829-determine-the-minimum-sum-of-a-k-avoiding-array/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2825. Make String a Subsequence Using Cyclic Increments</title>
		<link>https://zxi.mytechroad.com/blog/two-pointers/leetcode-2825-make-string-a-subsequence-using-cyclic-increments/</link>
					<comments>https://zxi.mytechroad.com/blog/two-pointers/leetcode-2825-make-string-a-subsequence-using-cyclic-increments/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 24 Aug 2023 04:38:17 +0000</pubDate>
				<category><![CDATA[Two pointers]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[subsequence]]></category>
		<category><![CDATA[two pointers]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10077</guid>

					<description><![CDATA[You are given two&#160;0-indexed&#160;strings&#160;str1&#160;and&#160;str2. In an operation, you select a&#160;set&#160;of indices in&#160;str1, and for each index&#160;i&#160;in the set, increment&#160;str1[i]&#160;to the next character&#160;cyclically. That is&#160;'a'&#160;becomes&#160;'b',&#160;'b'&#160;becomes&#160;'c', and&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given two&nbsp;<strong>0-indexed</strong>&nbsp;strings&nbsp;<code>str1</code>&nbsp;and&nbsp;<code>str2</code>.</p>



<p>In an operation, you select a&nbsp;<strong>set</strong>&nbsp;of indices in&nbsp;<code>str1</code>, and for each index&nbsp;<code>i</code>&nbsp;in the set, increment&nbsp;<code>str1[i]</code>&nbsp;to the next character&nbsp;<strong>cyclically</strong>. That is&nbsp;<code>'a'</code>&nbsp;becomes&nbsp;<code>'b'</code>,&nbsp;<code>'b'</code>&nbsp;becomes&nbsp;<code>'c'</code>, and so on, and&nbsp;<code>'z'</code>&nbsp;becomes&nbsp;<code>'a'</code>.</p>



<p>Return&nbsp;<code>true</code>&nbsp;<em>if it is possible to make&nbsp;</em><code>str2</code>&nbsp;<em>a subsequence of&nbsp;</em><code>str1</code>&nbsp;<em>by performing the operation&nbsp;<strong>at most once</strong></em>,&nbsp;<em>and</em>&nbsp;<code>false</code>&nbsp;<em>otherwise</em>.</p>



<p><strong>Note:</strong>&nbsp;A subsequence of a string is a new string that is formed from the original string by deleting some (possibly none) of the characters without disturbing the relative positions of the remaining characters.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> str1 = "abc", str2 = "ad"
<strong>Output:</strong> true
<strong>Explanation:</strong> Select index 2 in str1.
Increment str1[2] to become 'd'. 
Hence, str1 becomes "abd" and str2 is now a subsequence. Therefore, true is returned.</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> str1 = "zc", str2 = "ad"
<strong>Output:</strong> true
<strong>Explanation:</strong> Select indices 0 and 1 in str1. 
Increment str1[0] to become 'a'. 
Increment str1[1] to become 'd'. 
Hence, str1 becomes "ad" and str2 is now a subsequence. Therefore, true is returned.</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> str1 = "ab", str2 = "d"
<strong>Output:</strong> false
<strong>Explanation:</strong> In this example, it can be shown that it is impossible to make str2 a subsequence of str1 using the operation at most once. 
Therefore, false is returned.</pre>



<p><strong>Constraints:</strong></p>



<ul class="wp-block-list"><li><code>1 &lt;= str1.length &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= str2.length &lt;= 10<sup>5</sup></code></li><li><code>str1</code>&nbsp;and&nbsp;<code>str2</code>&nbsp;consist of only lowercase English letters.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: Two pointers</strong></h2>



<p>s1[i] and s2[j] can match if <br>s1[i] == s2[j] or inc(s1[i]) == s2[j]</p>



<p>If matched: ++i; ++j else ++i.</p>



<p>Time complexity: O(n)<br>Space complexity: O(1)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  bool canMakeSubsequence(string_view s1, string_view s2) {    
    for (int i = 0, j = 0, n = s1.size(), m = s2.size(); i &lt; n; ++i)
      if (s1[i] == s2[j] || (s1[i] - 'a' + 1) % 26 == s2[j] - 'a')
        if (++j == m) return true;
    return false;
  }
};</pre>
</div></div>



<p>Iterator version</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  bool canMakeSubsequence(string_view s1, string_view s2) {    
    for (auto i = begin(s1), j = begin(s2); i != end(s1); ++i)
      if (*i == *j || (*i - 'a' + 1) % 26 == *j - 'a')
        if (++j == end(s2)) return true;
    return false;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/two-pointers/leetcode-2825-make-string-a-subsequence-using-cyclic-increments/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2771. Longest Non-decreasing Subarray From Two Arrays</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2771-longest-non-decreasing-subarray-from-two-arrays/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2771-longest-non-decreasing-subarray-from-two-arrays/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 15 Jul 2023 15:50:52 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10063</guid>

					<description><![CDATA[You are given two&#160;0-indexed&#160;integer arrays&#160;nums1&#160;and&#160;nums2&#160;of length&#160;n. Let&#8217;s define another&#160;0-indexed&#160;integer array,&#160;nums3, of length&#160;n. For each index&#160;i&#160;in the range&#160;[0, n - 1], you can assign either&#160;nums1[i]&#160;or&#160;nums2[i]&#160;to&#160;nums3[i]. Your&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given two&nbsp;<strong>0-indexed</strong>&nbsp;integer arrays&nbsp;<code>nums1</code>&nbsp;and&nbsp;<code>nums2</code>&nbsp;of length&nbsp;<code>n</code>.</p>



<p>Let&#8217;s define another&nbsp;<strong>0-indexed</strong>&nbsp;integer array,&nbsp;<code>nums3</code>, of length&nbsp;<code>n</code>. For each index&nbsp;<code>i</code>&nbsp;in the range&nbsp;<code>[0, n - 1]</code>, you can assign either&nbsp;<code>nums1[i]</code>&nbsp;or&nbsp;<code>nums2[i]</code>&nbsp;to&nbsp;<code>nums3[i]</code>.</p>



<p>Your task is to maximize the length of the&nbsp;<strong>longest non-decreasing subarray</strong>&nbsp;in&nbsp;<code>nums3</code>&nbsp;by choosing its values optimally.</p>



<p>Return&nbsp;<em>an integer representing the length of the&nbsp;<strong>longest non-decreasing</strong>&nbsp;subarray in</em>&nbsp;<code>nums3</code>.</p>



<p><strong>Note:&nbsp;</strong>A&nbsp;<strong>subarray</strong>&nbsp;is a contiguous&nbsp;<strong>non-empty</strong>&nbsp;sequence of elements within an array.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums1 = [2,3,1], nums2 = [1,2,1]
<strong>Output:</strong> 2
<strong>Explanation: </strong>One way to construct nums3 is: 
nums3 = [nums1[0], nums2[1], nums2[2]] =&gt; [2,2,1]. 
The subarray starting from index 0 and ending at index 1, [2,2], forms a non-decreasing subarray of length 2. 
We can show that 2 is the maximum achievable length.</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums1 = [1,3,2,1], nums2 = [2,2,3,4]
<strong>Output:</strong> 4
<strong>Explanation:</strong> One way to construct nums3 is: 
nums3 = [nums1[0], nums2[1], nums2[2], nums2[3]] =&gt; [1,2,3,4]. 
The entire array forms a non-decreasing subarray of length 4, making it the maximum achievable length.
</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums1 = [1,1], nums2 = [2,2]
<strong>Output:</strong> 2
<strong>Explanation:</strong> One way to construct nums3 is: 
nums3 = [nums1[0], nums1[1]] =&gt; [1,1]. 
The entire array forms a non-decreasing subarray of length 2, making it the maximum achievable length.
</pre>



<p><strong>Constraints:</strong></p>



<ul class="wp-block-list"><li><code>1 &lt;= nums1.length == nums2.length == n &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= nums1[i], nums2[i] &lt;= 10<sup>9</sup></code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: DP</strong></h2>



<p>Let dp1(i), dp2(i) denote the length of the Longest Non-decreasing Subarray ends with nums1[i] and nums2[i] respectively.</p>



<p>init: dp1(0) = dp2(0) = 1</p>



<p>dp1(i) = max(dp1(i &#8211; 1) + 1 if nums1[i] &gt;= nums1[i &#8211; 1] else 1, dp2(i &#8211; 1) + 1 if nums1[i] &gt;= nums2[i &#8211; 1] else 1)<br>dp2(i) = max(dp1(i &#8211; 1) + 1 if nums2[i] &gt;= nums1[i &#8211; 1] else 1, dp2(i &#8211; 1) + 1 if nums2[i] &gt;= nums2[i &#8211; 1] else 1)</p>



<p>ans = max(dp1, dp2)</p>



<p>Time complexity: O(n)<br>Space complexity: O(n) -&gt; O(1)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">Python3</h2>
<div class="tabcontent">

<pre class="urvanov-syntax-highlighter-plain-tag"># Author: Huahua
class Solution:
  def maxNonDecreasingLength(self, nums1: List[int], nums2: List[int]) -&amp;gt; int:
    n = len(nums1)
    nums = [nums1, nums2]

    @cache
    def dp(i: int, j: int):
      if i == 0: return 1
      ans = 1
      for k in range(2):
        if nums[j][i] &gt;= nums[k][i - 1]:
          ans = max(ans, dp(i - 1, k) + 1)
      return ans

    return max(max(dp(i, 0), dp(i, 1)) for i in range(n))</pre>
</div></div>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  int maxNonDecreasingLength(vector&lt;int&gt;&amp; nums1, vector&lt;int&gt;&amp; nums2) {
    int ans = 1;
    for (int i = 1, dp1 = 1, dp2 = 1; i &lt; nums1.size(); ++i) {
      int t1 = max(nums1[i] &gt;= nums1[i - 1] ? dp1 + 1 : 1, 
                   nums1[i] &gt;= nums2[i - 1] ? dp2 + 1 : 1);
      int t2 = max(nums2[i] &gt;= nums1[i - 1] ? dp1 + 1 : 1, 
                   nums2[i] &gt;= nums2[i - 1] ? dp2 + 1 : 1);
      dp1 = t1;
      dp2 = t2;
      ans = max({ans, dp1, dp2});
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2771-longest-non-decreasing-subarray-from-two-arrays/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
