From 7a8e930a6548df9680214fde10ffff9fd0a9235b Mon Sep 17 00:00:00 2001 From: yanglbme <szuyanglb@outlook.com> Date: Tue, 24 Sep 2024 09:11:36 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.1239 No.1239.Maximum Length of a Concatenated String with Unique Characters --- .../README.md | 178 +++++++++++------- .../README_EN.md | 178 +++++++++++------- .../Solution.cpp | 34 ++-- .../Solution.go | 35 ++-- .../Solution.java | 36 ++-- .../Solution.py | 26 +-- .../Solution.ts | 36 ++++ 7 files changed, 310 insertions(+), 213 deletions(-) create mode 100644 solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.ts diff --git a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README.md b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README.md index 5c8121c3866f2..dce090b353afa 100644 --- a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README.md +++ b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README.md @@ -75,11 +75,17 @@ tags: <!-- solution:start --> -### 方法一:位运算 + 状态压缩 +### 方法一:状态压缩 + 位运算 -状态压缩,用一个 $32$ 位数记录字母的出现情况,`masks` 存储之前枚举的字符串。 +由于题目要求子序列的字符不能重复,字符都是小写字母,因此,我们可以用一个长度为 $26$ 的二进制整数来表示一个子序列,其中第 $i$ 位为 $1$ 表示子序列中含有滴 $i$ 个字符,为 $0$ 表示不含有第 $i$ 个字符。 -时间复杂度 $O(2^n + L)$,空间复杂度 $O(2^n)$。其中 $n$ 和 $L$ 分别是字符串数组的长度和字符串数组中字符串的长度之和。 +我们可以用一个数组 $s$ 来存储所有满足条件的子序列的状态,初始时 $s$ 中只有一个元素 $0$。 + +然后我们遍历数组 $\textit{arr}$,对于每个字符串 $t$,我们用一个整数 $x$ 来表示 $t$ 的状态,然后我们遍历数组 $s$,对于每个状态 $y$,如果 $x$ 和 $y$ 之间没有相同的字符,那么我们将 $x$ 和 $y$ 的并集加入到 $s$ 中,并更新答案。 + +最后我们返回答案即可。 + +时间复杂度 $O(2^n + L)$,空间复杂度 $O(2^n)$,其中 $n$ 是字符串数组的长度,而 $L$ 是字符串数组中所有字符串的长度之和。 <!-- tabs:start --> @@ -88,23 +94,17 @@ tags: ```python class Solution: def maxLength(self, arr: List[str]) -> int: - ans = 0 - masks = [0] - for s in arr: - mask = 0 - for c in s: - i = ord(c) - ord('a') - if mask >> i & 1: - mask = 0 + s = [0] + for t in arr: + x = 0 + for b in map(lambda c: ord(c) - 97, t): + if x >> b & 1: + x = 0 break - mask |= 1 << i - if mask == 0: - continue - for m in masks: - if m & mask == 0: - masks.append(m | mask) - ans = max(ans, (m | mask).bit_count()) - return ans + x |= 1 << b + if x: + s.extend((x | y) for y in s if (x & y) == 0) + return max(x.bit_count() for x in s) ``` #### Java @@ -112,28 +112,26 @@ class Solution: ```java class Solution { public int maxLength(List<String> arr) { + List<Integer> s = new ArrayList<>(); + s.add(0); int ans = 0; - List<Integer> masks = new ArrayList<>(); - masks.add(0); - for (var s : arr) { - int mask = 0; - for (int i = 0; i < s.length(); ++i) { - int j = s.charAt(i) - 'a'; - if (((mask >> j) & 1) == 1) { - mask = 0; + for (var t : arr) { + int x = 0; + for (char c : t.toCharArray()) { + int b = c - 'a'; + if ((x >> b & 1) == 1) { + x = 0; break; } - mask |= 1 << j; + x |= 1 << b; } - if (mask == 0) { - continue; - } - int n = masks.size(); - for (int i = 0; i < n; ++i) { - int m = masks.get(i); - if ((m & mask) == 0) { - masks.add(m | mask); - ans = Math.max(ans, Integer.bitCount(m | mask)); + if (x > 0) { + for (int i = s.size() - 1; i >= 0; --i) { + int y = s.get(i); + if ((x & y) == 0) { + s.add(x | y); + ans = Math.max(ans, Integer.bitCount(x | y)); + } } } } @@ -148,27 +146,25 @@ class Solution { class Solution { public: int maxLength(vector<string>& arr) { + vector<int> s = {0}; int ans = 0; - vector<int> masks = {0}; - for (auto& s : arr) { - int mask = 0; - for (auto& c : s) { - int i = c - 'a'; - if (mask >> i & 1) { - mask = 0; + for (const string& t : arr) { + int x = 0; + for (char c : t) { + int b = c - 'a'; + if ((x >> b & 1) == 1) { + x = 0; break; } - mask |= 1 << i; - } - if (mask == 0) { - continue; + x |= 1 << b; } - int n = masks.size(); - for (int i = 0; i < n; ++i) { - int m = masks[i]; - if ((m & mask) == 0) { - masks.push_back(m | mask); - ans = max(ans, __builtin_popcount(m | mask)); + if (x > 0) { + for (int i = s.size() - 1; i >= 0; --i) { + int y = s[i]; + if ((x & y) == 0) { + s.push_back(x | y); + ans = max(ans, __builtin_popcount(x | y)); + } } } } @@ -181,29 +177,69 @@ public: ```go func maxLength(arr []string) (ans int) { - masks := []int{0} - for _, s := range arr { - mask := 0 - for _, c := range s { - i := int(c - 'a') - if mask>>i&1 == 1 { - mask = 0 + s := []int{0} + for _, t := range arr { + x := 0 + for _, c := range t { + b := int(c - 'a') + if (x>>b)&1 == 1 { + x = 0 break } - mask |= 1 << i + x |= 1 << b } - if mask == 0 { - continue - } - n := len(masks) - for _, m := range masks[:n] { - if m&mask == 0 { - masks = append(masks, m|mask) - ans = max(ans, bits.OnesCount(uint(m|mask))) + if x > 0 { + for i := len(s) - 1; i >= 0; i-- { + y := s[i] + if (x & y) == 0 { + s = append(s, x|y) + ans = max(ans, bits.OnesCount(uint(x|y))) + } } } } - return + return ans +} +``` + +#### TypeScript + +```ts +function maxLength(arr: string[]): number { + const s: number[] = [0]; + let ans = 0; + for (const t of arr) { + let x = 0; + for (const c of t) { + const b = c.charCodeAt(0) - 97; + if ((x >> b) & 1) { + x = 0; + break; + } + x |= 1 << b; + } + + if (x > 0) { + for (let i = s.length - 1; ~i; --i) { + const y = s[i]; + if ((x & y) === 0) { + s.push(x | y); + ans = Math.max(ans, bitCount(x | y)); + } + } + } + } + + return ans; +} + +function bitCount(i: number): number { + i = i - ((i >>> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); + i = (i + (i >>> 4)) & 0x0f0f0f0f; + i = i + (i >>> 8); + i = i + (i >>> 16); + return i & 0x3f; } ``` diff --git a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README_EN.md b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README_EN.md index dc8597040daba..260ee2b0ef79c 100644 --- a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README_EN.md +++ b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README_EN.md @@ -74,11 +74,17 @@ Maximum length is 4. <!-- solution:start --> -### Solution 1: Bit Manipulation + State Compression +### Solution 1: State Compression + Bit Manipulation -State compression is used, with a 32-bit number recording the occurrence of letters, and `masks` storing the strings enumerated before. +Since the problem requires that the characters in the subsequence must not be repeated and all characters are lowercase letters, we can use a binary integer of length $26$ to represent a subsequence. The $i$-th bit being $1$ indicates that the subsequence contains the $i$-th character, and $0$ indicates that it does not contain the $i$-th character. -The time complexity is $O(2^n + L)$, and the space complexity is $O(2^n)$. Where $n$ and $L$ are the length of the string array and the sum of the lengths of the strings in the array, respectively. +We can use an array $s$ to store the states of all subsequences that meet the conditions. Initially, $s$ contains only one element $0$. + +Then we traverse the array $\textit{arr}$. For each string $t$, we use an integer $x$ to represent the state of $t$. Then we traverse the array $s$. For each state $y$, if $x$ and $y$ have no common characters, we add the union of $x$ and $y$ to $s$ and update the answer. + +Finally, we return the answer. + +The time complexity is $O(2^n + L)$, and the space complexity is $O(2^n)$. Here, $n$ is the length of the string array, and $L$ is the sum of the lengths of all strings in the array. <!-- tabs:start --> @@ -87,23 +93,17 @@ The time complexity is $O(2^n + L)$, and the space complexity is $O(2^n)$. Where ```python class Solution: def maxLength(self, arr: List[str]) -> int: - ans = 0 - masks = [0] - for s in arr: - mask = 0 - for c in s: - i = ord(c) - ord('a') - if mask >> i & 1: - mask = 0 + s = [0] + for t in arr: + x = 0 + for b in map(lambda c: ord(c) - 97, t): + if x >> b & 1: + x = 0 break - mask |= 1 << i - if mask == 0: - continue - for m in masks: - if m & mask == 0: - masks.append(m | mask) - ans = max(ans, (m | mask).bit_count()) - return ans + x |= 1 << b + if x: + s.extend((x | y) for y in s if (x & y) == 0) + return max(x.bit_count() for x in s) ``` #### Java @@ -111,28 +111,26 @@ class Solution: ```java class Solution { public int maxLength(List<String> arr) { + List<Integer> s = new ArrayList<>(); + s.add(0); int ans = 0; - List<Integer> masks = new ArrayList<>(); - masks.add(0); - for (var s : arr) { - int mask = 0; - for (int i = 0; i < s.length(); ++i) { - int j = s.charAt(i) - 'a'; - if (((mask >> j) & 1) == 1) { - mask = 0; + for (var t : arr) { + int x = 0; + for (char c : t.toCharArray()) { + int b = c - 'a'; + if ((x >> b & 1) == 1) { + x = 0; break; } - mask |= 1 << j; + x |= 1 << b; } - if (mask == 0) { - continue; - } - int n = masks.size(); - for (int i = 0; i < n; ++i) { - int m = masks.get(i); - if ((m & mask) == 0) { - masks.add(m | mask); - ans = Math.max(ans, Integer.bitCount(m | mask)); + if (x > 0) { + for (int i = s.size() - 1; i >= 0; --i) { + int y = s.get(i); + if ((x & y) == 0) { + s.add(x | y); + ans = Math.max(ans, Integer.bitCount(x | y)); + } } } } @@ -147,27 +145,25 @@ class Solution { class Solution { public: int maxLength(vector<string>& arr) { + vector<int> s = {0}; int ans = 0; - vector<int> masks = {0}; - for (auto& s : arr) { - int mask = 0; - for (auto& c : s) { - int i = c - 'a'; - if (mask >> i & 1) { - mask = 0; + for (const string& t : arr) { + int x = 0; + for (char c : t) { + int b = c - 'a'; + if ((x >> b & 1) == 1) { + x = 0; break; } - mask |= 1 << i; - } - if (mask == 0) { - continue; + x |= 1 << b; } - int n = masks.size(); - for (int i = 0; i < n; ++i) { - int m = masks[i]; - if ((m & mask) == 0) { - masks.push_back(m | mask); - ans = max(ans, __builtin_popcount(m | mask)); + if (x > 0) { + for (int i = s.size() - 1; i >= 0; --i) { + int y = s[i]; + if ((x & y) == 0) { + s.push_back(x | y); + ans = max(ans, __builtin_popcount(x | y)); + } } } } @@ -180,29 +176,69 @@ public: ```go func maxLength(arr []string) (ans int) { - masks := []int{0} - for _, s := range arr { - mask := 0 - for _, c := range s { - i := int(c - 'a') - if mask>>i&1 == 1 { - mask = 0 + s := []int{0} + for _, t := range arr { + x := 0 + for _, c := range t { + b := int(c - 'a') + if (x>>b)&1 == 1 { + x = 0 break } - mask |= 1 << i + x |= 1 << b } - if mask == 0 { - continue - } - n := len(masks) - for _, m := range masks[:n] { - if m&mask == 0 { - masks = append(masks, m|mask) - ans = max(ans, bits.OnesCount(uint(m|mask))) + if x > 0 { + for i := len(s) - 1; i >= 0; i-- { + y := s[i] + if (x & y) == 0 { + s = append(s, x|y) + ans = max(ans, bits.OnesCount(uint(x|y))) + } } } } - return + return ans +} +``` + +#### TypeScript + +```ts +function maxLength(arr: string[]): number { + const s: number[] = [0]; + let ans = 0; + for (const t of arr) { + let x = 0; + for (const c of t) { + const b = c.charCodeAt(0) - 97; + if ((x >> b) & 1) { + x = 0; + break; + } + x |= 1 << b; + } + + if (x > 0) { + for (let i = s.length - 1; ~i; --i) { + const y = s[i]; + if ((x & y) === 0) { + s.push(x | y); + ans = Math.max(ans, bitCount(x | y)); + } + } + } + } + + return ans; +} + +function bitCount(i: number): number { + i = i - ((i >>> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); + i = (i + (i >>> 4)) & 0x0f0f0f0f; + i = i + (i >>> 8); + i = i + (i >>> 16); + return i & 0x3f; } ``` diff --git a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.cpp b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.cpp index 71e2653dcd012..76f4c50b2ac58 100644 --- a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.cpp +++ b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.cpp @@ -1,30 +1,28 @@ class Solution { public: int maxLength(vector<string>& arr) { + vector<int> s = {0}; int ans = 0; - vector<int> masks = {0}; - for (auto& s : arr) { - int mask = 0; - for (auto& c : s) { - int i = c - 'a'; - if (mask >> i & 1) { - mask = 0; + for (const string& t : arr) { + int x = 0; + for (char c : t) { + int b = c - 'a'; + if ((x >> b & 1) == 1) { + x = 0; break; } - mask |= 1 << i; + x |= 1 << b; } - if (mask == 0) { - continue; - } - int n = masks.size(); - for (int i = 0; i < n; ++i) { - int m = masks[i]; - if ((m & mask) == 0) { - masks.push_back(m | mask); - ans = max(ans, __builtin_popcount(m | mask)); + if (x > 0) { + for (int i = s.size() - 1; i >= 0; --i) { + int y = s[i]; + if ((x & y) == 0) { + s.push_back(x | y); + ans = max(ans, __builtin_popcount(x | y)); + } } } } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.go b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.go index f1f2f02c47eb3..095f0d2809e73 100644 --- a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.go +++ b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.go @@ -1,25 +1,24 @@ func maxLength(arr []string) (ans int) { - masks := []int{0} - for _, s := range arr { - mask := 0 - for _, c := range s { - i := int(c - 'a') - if mask>>i&1 == 1 { - mask = 0 + s := []int{0} + for _, t := range arr { + x := 0 + for _, c := range t { + b := int(c - 'a') + if (x>>b)&1 == 1 { + x = 0 break } - mask |= 1 << i + x |= 1 << b } - if mask == 0 { - continue - } - n := len(masks) - for _, m := range masks[:n] { - if m&mask == 0 { - masks = append(masks, m|mask) - ans = max(ans, bits.OnesCount(uint(m|mask))) + if x > 0 { + for i := len(s) - 1; i >= 0; i-- { + y := s[i] + if (x & y) == 0 { + s = append(s, x|y) + ans = max(ans, bits.OnesCount(uint(x|y))) + } } } } - return -} \ No newline at end of file + return ans +} diff --git a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.java b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.java index 47e50759aea30..fee4b6904b825 100644 --- a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.java +++ b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.java @@ -1,30 +1,28 @@ class Solution { public int maxLength(List<String> arr) { + List<Integer> s = new ArrayList<>(); + s.add(0); int ans = 0; - List<Integer> masks = new ArrayList<>(); - masks.add(0); - for (var s : arr) { - int mask = 0; - for (int i = 0; i < s.length(); ++i) { - int j = s.charAt(i) - 'a'; - if (((mask >> j) & 1) == 1) { - mask = 0; + for (var t : arr) { + int x = 0; + for (char c : t.toCharArray()) { + int b = c - 'a'; + if ((x >> b & 1) == 1) { + x = 0; break; } - mask |= 1 << j; + x |= 1 << b; } - if (mask == 0) { - continue; - } - int n = masks.size(); - for (int i = 0; i < n; ++i) { - int m = masks.get(i); - if ((m & mask) == 0) { - masks.add(m | mask); - ans = Math.max(ans, Integer.bitCount(m | mask)); + if (x > 0) { + for (int i = s.size() - 1; i >= 0; --i) { + int y = s.get(i); + if ((x & y) == 0) { + s.add(x | y); + ans = Math.max(ans, Integer.bitCount(x | y)); + } } } } return ans; } -} \ No newline at end of file +} diff --git a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.py b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.py index 1e63cce9be627..79fd149c270da 100644 --- a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.py +++ b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.py @@ -1,19 +1,13 @@ class Solution: def maxLength(self, arr: List[str]) -> int: - ans = 0 - masks = [0] - for s in arr: - mask = 0 - for c in s: - i = ord(c) - ord('a') - if mask >> i & 1: - mask = 0 + s = [0] + for t in arr: + x = 0 + for b in map(lambda c: ord(c) - 97, t): + if x >> b & 1: + x = 0 break - mask |= 1 << i - if mask == 0: - continue - for m in masks: - if m & mask == 0: - masks.append(m | mask) - ans = max(ans, (m | mask).bit_count()) - return ans + x |= 1 << b + if x: + s.extend((x | y) for y in s if (x & y) == 0) + return max(x.bit_count() for x in s) diff --git a/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.ts b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.ts new file mode 100644 index 0000000000000..15e3c3a6e7269 --- /dev/null +++ b/solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/Solution.ts @@ -0,0 +1,36 @@ +function maxLength(arr: string[]): number { + const s: number[] = [0]; + let ans = 0; + for (const t of arr) { + let x = 0; + for (const c of t) { + const b = c.charCodeAt(0) - 97; + if ((x >> b) & 1) { + x = 0; + break; + } + x |= 1 << b; + } + + if (x > 0) { + for (let i = s.length - 1; ~i; --i) { + const y = s[i]; + if ((x & y) === 0) { + s.push(x | y); + ans = Math.max(ans, bitCount(x | y)); + } + } + } + } + + return ans; +} + +function bitCount(i: number): number { + i = i - ((i >>> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); + i = (i + (i >>> 4)) & 0x0f0f0f0f; + i = i + (i >>> 8); + i = i + (i >>> 16); + return i & 0x3f; +}