From c8d31b522ba2f8cd2bf1106397474f5fcb1ef11e Mon Sep 17 00:00:00 2001 From: Richard Liu Date: Wed, 2 Mar 2022 05:38:09 -0800 Subject: [PATCH] 1888 --- .../README.md | 122 +++++++++++++----- 1 file changed, 88 insertions(+), 34 deletions(-) diff --git a/leetcode/1888. Minimum Number of Flips to Make the Binary String Alternating/README.md b/leetcode/1888. Minimum Number of Flips to Make the Binary String Alternating/README.md index 9202ddf6..00dd6c85 100644 --- a/leetcode/1888. Minimum Number of Flips to Make the Binary String Alternating/README.md +++ b/leetcode/1888. Minimum Number of Flips to Make the Binary String Alternating/README.md @@ -51,43 +51,48 @@ Then, use the second operation on the third and sixth elements to make s = "10= 0)` out of the window. We keep track of the count of flips needed within the window as `cnt` and return the global minimal `cnt` as the answer. ```cpp // OJ: https://leetcode.com/problems/minimum-number-of-flips-to-make-the-binary-string-alternating/ // Author: github.com/lzl124631x // Time: O(N) -// Space: O(N) +// Space: O(1) class Solution { - int even(string &s, int c) { - int ans = 0; - for (int i = 0; i < s.size(); ++i) { - ans += i % 2 ? (s[i] != c + '0') : (s[i] != '0' + (1 - c)); - } - return ans; - } - int odd(string &s, int c) { - int N = s.size(); - vector> dp(N + 1, vector(2)); - for (int i = 0; i < s.size(); ++i) { - dp[i + 1][1] = dp[i][1] + (i % 2 ? (s[i] != c + '0') : (s[i] != '0' + (1 - c))); - dp[i + 1][0] = min(dp[i][1], dp[i][0]) + (i % 2 == 0? (s[i] != c + '0') : (s[i] != '0' + (1 - c))); - } - return min(dp[N][0], dp[N][1]); - } public: int minFlips(string s) { - if (s.size() % 2 == 0) { - return min(even(s, 0), even(s, 1)); - } - return min(odd(s, 0), odd(s, 1)); + int N = s.size(); + auto solve = [&](char c) { + int ans = INT_MAX, cnt = 0; + for (int i = 0; i < 2 * N; ++i) { + cnt += s[i % N] == c ^ (i % 2); + if (i - N >= 0) cnt -= s[i - N] == c ^ ((i - N) % 2) ; + if (i >= N - 1) ans = min(ans, cnt); + } + return ans; + }; + return min(solve('0'), solve('1')); } }; ``` -## Solution 2. +The following is a fool-proof implementation (good to use during contest), but takes `O(N)` space. ```cpp // OJ: https://leetcode.com/problems/minimum-number-of-flips-to-make-the-binary-string-alternating/ @@ -99,19 +104,19 @@ class Solution { public: int minFlips(string s) { int N = s.size(), c1 = 0, c2 = 0, ans = INT_MAX; - s += s; - string x, y; + s += s; // simulating cyclic string + string x, y; // the target strings for (int i = 0; i < 2 * N; ++i) { x += i % 2 ? '1' : '0'; y += i % 2 ? '0' : '1'; } for (int i = 0; i < 2 * N; ++i) { + c1 += x[i] != s[i]; + c2 += y[i] != s[i]; if (i - N >= 0) { c1 -= x[i - N] != s[i - N]; c2 -= y[i - N] != s[i - N]; } - c1 += x[i] != s[i]; - c2 += y[i] != s[i]; if (i >= N - 1) ans = min({ ans, c1, c2 }); } return ans; @@ -119,7 +124,56 @@ public: }; ``` -## Solution 3. +## Solution 2. + +Due to symmetry, if making the result string start with character `0` requires `t` steps, then making the result string start with character `1` requires `N - t` steps. + +If the length of `s` is even, picking any index `j > 0` as starting index is equivalent to picking `i = 0` as the starting index and possibly flipping the target string. + +For example, `s = "0110"`, if we pick `j = 1` as the starting index + +``` + v +0110 +1010 // target string = "0101" starts from index 1. +// this is equivalent to +v +0110 +1010 // target string = "1010" starts from index 0 +``` + +So, if the length of `s` is even, the answer is `min(t, N - t)`. + +When the length of `s` is odd, if we make `i = 1` as the starting index, we need to do the following: + +1. Flip the target string. The number of steps needed to make the result string start with character `0` is now `N - t`. +2. Make adjustment for `s[i]`. + +For example: + +``` + s = "01101" +target = "01010" + --- + t = 3 +// Now let index 1 be the starting index + v + s = "01101" +target = "00101" +// This is the same as +// Step 1: + v + s = "01101" +target = "10101" // flipping the original target string + t = N - t // the number of flips is also flipped +// Step 2: + v + s = "01101" +target = "00101" // adjustment for s[0] +// If s[0] == '0', we need to minus 1 +// If s[0] == '1', we need to plus 1. +// So, the adjustment is to plus `s[i] == '0' ? -1 : 1`. +``` ```cpp // OJ: https://leetcode.com/problems/minimum-number-of-flips-to-make-the-binary-string-alternating/ @@ -130,11 +184,11 @@ class Solution { public: int minFlips(string s) { int N = s.size(), t = 0; - for (int i = 0; i < N; ++i) t += (s[i] == '0') ^ (i % 2 == 0); - int ans = min(t, N - t); - if (N % 2 == 0) return ans; - for (int i = 0; i < N - 1; ++i) { - t = N - t + (s[i] == '0' ? -1 : 1); + for (int i = 0; i < N; ++i) t += (s[i] == '0') ^ (i % 2 == 0); // `t` is the number of flips needed to make the result string start with character `0`. + int ans = min(t, N - t); // `N - t` is the number of flips needed to make the result string start with character `1`. + if (N % 2 == 0) return ans; // If `N` is even, the answer is `min(t, N - t)`. + for (int i = 0; i < N - 1; ++i) { // If `N` is odd, we try making `i+1` as the starting index + t = N - t + (s[i] == '0' ? -1 : 1); // flipping all the target characters make t -> N - t. We need adjust for `s[i]`. ans = min(ans, min(t, N - t)); } return ans;