Skip to content

Commit cf2a9dd

Browse files
authored
feat: add solutions to lc problem: No.1239 (doocs#3555)
No.1239.Maximum Length of a Concatenated String with Unique Characters
1 parent 42478e4 commit cf2a9dd

File tree

7 files changed

+310
-213
lines changed

7 files changed

+310
-213
lines changed

solution/1200-1299/1239.Maximum Length of a Concatenated String with Unique Characters/README.md

+107-71
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,17 @@ tags:
7575

7676
<!-- solution:start -->
7777

78-
### 方法一:位运算 + 状态压缩
78+
### 方法一:状态压缩 + 位运算
7979

80-
状态压缩,用一个 $32$ 位数记录字母的出现情况,`masks` 存储之前枚举的字符串
80+
由于题目要求子序列的字符不能重复,字符都是小写字母,因此,我们可以用一个长度为 $26$ 的二进制整数来表示一个子序列,其中第 $i$ 位为 $1$ 表示子序列中含有滴 $i$ 个字符,为 $0$ 表示不含有第 $i$ 个字符
8181

82-
时间复杂度 $O(2^n + L)$,空间复杂度 $O(2^n)$。其中 $n$ 和 $L$ 分别是字符串数组的长度和字符串数组中字符串的长度之和。
82+
我们可以用一个数组 $s$ 来存储所有满足条件的子序列的状态,初始时 $s$ 中只有一个元素 $0$。
83+
84+
然后我们遍历数组 $\textit{arr}$,对于每个字符串 $t$,我们用一个整数 $x$ 来表示 $t$ 的状态,然后我们遍历数组 $s$,对于每个状态 $y$,如果 $x$ 和 $y$ 之间没有相同的字符,那么我们将 $x$ 和 $y$ 的并集加入到 $s$ 中,并更新答案。
85+
86+
最后我们返回答案即可。
87+
88+
时间复杂度 $O(2^n + L)$,空间复杂度 $O(2^n)$,其中 $n$ 是字符串数组的长度,而 $L$ 是字符串数组中所有字符串的长度之和。
8389

8490
<!-- tabs:start -->
8591

@@ -88,52 +94,44 @@ tags:
8894
```python
8995
class Solution:
9096
def maxLength(self, arr: List[str]) -> int:
91-
ans = 0
92-
masks = [0]
93-
for s in arr:
94-
mask = 0
95-
for c in s:
96-
i = ord(c) - ord('a')
97-
if mask >> i & 1:
98-
mask = 0
97+
s = [0]
98+
for t in arr:
99+
x = 0
100+
for b in map(lambda c: ord(c) - 97, t):
101+
if x >> b & 1:
102+
x = 0
99103
break
100-
mask |= 1 << i
101-
if mask == 0:
102-
continue
103-
for m in masks:
104-
if m & mask == 0:
105-
masks.append(m | mask)
106-
ans = max(ans, (m | mask).bit_count())
107-
return ans
104+
x |= 1 << b
105+
if x:
106+
s.extend((x | y) for y in s if (x & y) == 0)
107+
return max(x.bit_count() for x in s)
108108
```
109109

110110
#### Java
111111

112112
```java
113113
class Solution {
114114
public int maxLength(List<String> arr) {
115+
List<Integer> s = new ArrayList<>();
116+
s.add(0);
115117
int ans = 0;
116-
List<Integer> masks = new ArrayList<>();
117-
masks.add(0);
118-
for (var s : arr) {
119-
int mask = 0;
120-
for (int i = 0; i < s.length(); ++i) {
121-
int j = s.charAt(i) - 'a';
122-
if (((mask >> j) & 1) == 1) {
123-
mask = 0;
118+
for (var t : arr) {
119+
int x = 0;
120+
for (char c : t.toCharArray()) {
121+
int b = c - 'a';
122+
if ((x >> b & 1) == 1) {
123+
x = 0;
124124
break;
125125
}
126-
mask |= 1 << j;
126+
x |= 1 << b;
127127
}
128-
if (mask == 0) {
129-
continue;
130-
}
131-
int n = masks.size();
132-
for (int i = 0; i < n; ++i) {
133-
int m = masks.get(i);
134-
if ((m & mask) == 0) {
135-
masks.add(m | mask);
136-
ans = Math.max(ans, Integer.bitCount(m | mask));
128+
if (x > 0) {
129+
for (int i = s.size() - 1; i >= 0; --i) {
130+
int y = s.get(i);
131+
if ((x & y) == 0) {
132+
s.add(x | y);
133+
ans = Math.max(ans, Integer.bitCount(x | y));
134+
}
137135
}
138136
}
139137
}
@@ -148,27 +146,25 @@ class Solution {
148146
class Solution {
149147
public:
150148
int maxLength(vector<string>& arr) {
149+
vector<int> s = {0};
151150
int ans = 0;
152-
vector<int> masks = {0};
153-
for (auto& s : arr) {
154-
int mask = 0;
155-
for (auto& c : s) {
156-
int i = c - 'a';
157-
if (mask >> i & 1) {
158-
mask = 0;
151+
for (const string& t : arr) {
152+
int x = 0;
153+
for (char c : t) {
154+
int b = c - 'a';
155+
if ((x >> b & 1) == 1) {
156+
x = 0;
159157
break;
160158
}
161-
mask |= 1 << i;
162-
}
163-
if (mask == 0) {
164-
continue;
159+
x |= 1 << b;
165160
}
166-
int n = masks.size();
167-
for (int i = 0; i < n; ++i) {
168-
int m = masks[i];
169-
if ((m & mask) == 0) {
170-
masks.push_back(m | mask);
171-
ans = max(ans, __builtin_popcount(m | mask));
161+
if (x > 0) {
162+
for (int i = s.size() - 1; i >= 0; --i) {
163+
int y = s[i];
164+
if ((x & y) == 0) {
165+
s.push_back(x | y);
166+
ans = max(ans, __builtin_popcount(x | y));
167+
}
172168
}
173169
}
174170
}
@@ -181,29 +177,69 @@ public:
181177
182178
```go
183179
func maxLength(arr []string) (ans int) {
184-
masks := []int{0}
185-
for _, s := range arr {
186-
mask := 0
187-
for _, c := range s {
188-
i := int(c - 'a')
189-
if mask>>i&1 == 1 {
190-
mask = 0
180+
s := []int{0}
181+
for _, t := range arr {
182+
x := 0
183+
for _, c := range t {
184+
b := int(c - 'a')
185+
if (x>>b)&1 == 1 {
186+
x = 0
191187
break
192188
}
193-
mask |= 1 << i
189+
x |= 1 << b
194190
}
195-
if mask == 0 {
196-
continue
197-
}
198-
n := len(masks)
199-
for _, m := range masks[:n] {
200-
if m&mask == 0 {
201-
masks = append(masks, m|mask)
202-
ans = max(ans, bits.OnesCount(uint(m|mask)))
191+
if x > 0 {
192+
for i := len(s) - 1; i >= 0; i-- {
193+
y := s[i]
194+
if (x & y) == 0 {
195+
s = append(s, x|y)
196+
ans = max(ans, bits.OnesCount(uint(x|y)))
197+
}
203198
}
204199
}
205200
}
206-
return
201+
return ans
202+
}
203+
```
204+
205+
#### TypeScript
206+
207+
```ts
208+
function maxLength(arr: string[]): number {
209+
const s: number[] = [0];
210+
let ans = 0;
211+
for (const t of arr) {
212+
let x = 0;
213+
for (const c of t) {
214+
const b = c.charCodeAt(0) - 97;
215+
if ((x >> b) & 1) {
216+
x = 0;
217+
break;
218+
}
219+
x |= 1 << b;
220+
}
221+
222+
if (x > 0) {
223+
for (let i = s.length - 1; ~i; --i) {
224+
const y = s[i];
225+
if ((x & y) === 0) {
226+
s.push(x | y);
227+
ans = Math.max(ans, bitCount(x | y));
228+
}
229+
}
230+
}
231+
}
232+
233+
return ans;
234+
}
235+
236+
function bitCount(i: number): number {
237+
i = i - ((i >>> 1) & 0x55555555);
238+
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
239+
i = (i + (i >>> 4)) & 0x0f0f0f0f;
240+
i = i + (i >>> 8);
241+
i = i + (i >>> 16);
242+
return i & 0x3f;
207243
}
208244
```
209245

0 commit comments

Comments
 (0)