Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lc problem: No.3076 #2439

Merged
merged 1 commit into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

### 方法一:快慢指针

我们定义两个指针 $a$ 和 $b$,初始时都指向链表的头节点。每次迭代时,$a$ 指针向前移动一步,$b$ 指针向前移动两步,直到 $b$ 指针到达链表的末尾。此时,$a$ 指针指向链表节点数的一半,我们将链表从 $a$ 指针处断开,即可得到两个链表的头节点。
我们定义两个指针 $a$ 和 $b$,初始时都指向链表的头节点。每次迭代时,指针 $a$ 向前移动一步,指针 $b$ 向前移动两步,直到指针 $b$ 到达链表的末尾。此时,指针 $a$ 指向链表节点数的一半,我们将链表从指针 $a$ 处断开,即可得到两个链表的头节点。

时间复杂度 $O(n)$,其中 $n$ 是链表的长度。需要遍历链表一次。空间复杂度 $O(1)$。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@

## Solutions

### Solution 1
### Solution 1: Fast and Slow Pointers

We define two pointers $a$ and $b$, both initially pointing to the head of the linked list. Each iteration, pointer $a$ moves forward one step, and pointer $b$ moves forward two steps, until pointer $b$ reaches the end of the linked list. At this point, pointer $a$ points to half of the linked list nodes, and we break the linked list from pointer $a$, thus obtaining the head nodes of the two linked lists.

The time complexity is $O(n)$, where $n$ is the length of the linked list. It requires one traversal of the linked list. The space complexity is $O(1)$.

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,145 @@

## 解法

### 方法一
### 方法一:枚举

我们注意到数据规模很小,所以可以直接枚举每个字符串的所有子串,然后判断是否是其他字符串的子串。

具体地,我们先枚举每个字符串 `arr[i]`,然后从小到大枚举每个子串的长度 $j$,然后枚举每个子串的起始位置 $l$,可以得到当前子串为 `sub = arr[i][l:l+j]`,然后判断 `sub` 是否是其他字符串的子串,如果是的话,就跳过当前子串,否则更新答案。

时间复杂度 $O(n^2 \times m^4)$,空间复杂度 $O(m)$。其中 $n$ 是字符串数组 `arr` 的长度,而 $m$ 是字符串的最大长度,本题中 $m \le 20$。

<!-- tabs:start -->

```python

class Solution:
def shortestSubstrings(self, arr: List[str]) -> List[str]:
ans = [""] * len(arr)
for i, s in enumerate(arr):
m = len(s)
for j in range(1, m + 1):
for l in range(m - j + 1):
sub = s[l : l + j]
if not ans[i] or ans[i] > sub:
if all(k == i or sub not in t for k, t in enumerate(arr)):
ans[i] = sub
if ans[i]:
break
return ans
```

```java

class Solution {
public String[] shortestSubstrings(String[] arr) {
int n = arr.length;
String[] ans = new String[n];
Arrays.fill(ans, "");
for (int i = 0; i < n; ++i) {
int m = arr[i].length();
for (int j = 1; j <= m && ans[i].isEmpty(); ++j) {
for (int l = 0; l <= m - j; ++l) {
String sub = arr[i].substring(l, l + j);
if (ans[i].isEmpty() || sub.compareTo(ans[i]) < 0) {
boolean ok = true;
for (int k = 0; k < n && ok; ++k) {
if (k != i && arr[k].contains(sub)) {
ok = false;
}
}
if (ok) {
ans[i] = sub;
}
}
}
}
}
return ans;
}
}
```

```cpp

class Solution {
public:
vector<string> shortestSubstrings(vector<string>& arr) {
int n = arr.size();
vector<string> ans(n);
for (int i = 0; i < n; ++i) {
int m = arr[i].size();
for (int j = 1; j <= m && ans[i].empty(); ++j) {
for (int l = 0; l <= m - j; ++l) {
string sub = arr[i].substr(l, j);
if (ans[i].empty() || sub < ans[i]) {
bool ok = true;
for (int k = 0; k < n && ok; ++k) {
if (k != i && arr[k].find(sub) != string::npos) {
ok = false;
}
}
if (ok) {
ans[i] = sub;
}
}
}
}
}
return ans;
}
};
```

```go
func shortestSubstrings(arr []string) []string {
ans := make([]string, len(arr))
for i, s := range arr {
m := len(s)
for j := 1; j <= m && len(ans[i]) == 0; j++ {
for l := 0; l <= m-j; l++ {
sub := s[l : l+j]
if len(ans[i]) == 0 || ans[i] > sub {
ok := true
for k, t := range arr {
if k != i && strings.Contains(t, sub) {
ok = false
break
}
}
if ok {
ans[i] = sub
}
}
}
}
}
return ans
}
```

```ts
function shortestSubstrings(arr: string[]): string[] {
const n: number = arr.length;
const ans: string[] = Array(n).fill('');
for (let i = 0; i < n; ++i) {
const m: number = arr[i].length;
for (let j = 1; j <= m && ans[i] === ''; ++j) {
for (let l = 0; l <= m - j; ++l) {
const sub: string = arr[i].slice(l, l + j);
if (ans[i] === '' || sub.localeCompare(ans[i]) < 0) {
let ok: boolean = true;
for (let k = 0; k < n && ok; ++k) {
if (k !== i && arr[k].includes(sub)) {
ok = false;
}
}
if (ok) {
ans[i] = sub;
}
}
}
}
}
return ans;
}
```

<!-- tabs:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,145 @@

## Solutions

### Solution 1
### Solution 1: Enumeration

Given the small data scale, we can directly enumerate all substrings of each string and then determine whether it is a substring of other strings.

Specifically, we first enumerate each string `arr[i]`, then enumerate the length $j$ of each substring from small to large, and then enumerate the starting position $l$ of each substring. We can get the current substring as `sub = arr[i][l:l+j]`. Then we determine whether `sub` is a substring of other strings. If it is, we skip the current substring; otherwise, we update the answer.

The time complexity is $O(n^2 \times m^4)$, and the space complexity is $O(m)$. Where $n$ is the length of the string array `arr`, and $m$ is the maximum length of the string. In this problem, $m \le 20$.

<!-- tabs:start -->

```python

class Solution:
def shortestSubstrings(self, arr: List[str]) -> List[str]:
ans = [""] * len(arr)
for i, s in enumerate(arr):
m = len(s)
for j in range(1, m + 1):
for l in range(m - j + 1):
sub = s[l : l + j]
if not ans[i] or ans[i] > sub:
if all(k == i or sub not in t for k, t in enumerate(arr)):
ans[i] = sub
if ans[i]:
break
return ans
```

```java

class Solution {
public String[] shortestSubstrings(String[] arr) {
int n = arr.length;
String[] ans = new String[n];
Arrays.fill(ans, "");
for (int i = 0; i < n; ++i) {
int m = arr[i].length();
for (int j = 1; j <= m && ans[i].isEmpty(); ++j) {
for (int l = 0; l <= m - j; ++l) {
String sub = arr[i].substring(l, l + j);
if (ans[i].isEmpty() || sub.compareTo(ans[i]) < 0) {
boolean ok = true;
for (int k = 0; k < n && ok; ++k) {
if (k != i && arr[k].contains(sub)) {
ok = false;
}
}
if (ok) {
ans[i] = sub;
}
}
}
}
}
return ans;
}
}
```

```cpp

class Solution {
public:
vector<string> shortestSubstrings(vector<string>& arr) {
int n = arr.size();
vector<string> ans(n);
for (int i = 0; i < n; ++i) {
int m = arr[i].size();
for (int j = 1; j <= m && ans[i].empty(); ++j) {
for (int l = 0; l <= m - j; ++l) {
string sub = arr[i].substr(l, j);
if (ans[i].empty() || sub < ans[i]) {
bool ok = true;
for (int k = 0; k < n && ok; ++k) {
if (k != i && arr[k].find(sub) != string::npos) {
ok = false;
}
}
if (ok) {
ans[i] = sub;
}
}
}
}
}
return ans;
}
};
```

```go
func shortestSubstrings(arr []string) []string {
ans := make([]string, len(arr))
for i, s := range arr {
m := len(s)
for j := 1; j <= m && len(ans[i]) == 0; j++ {
for l := 0; l <= m-j; l++ {
sub := s[l : l+j]
if len(ans[i]) == 0 || ans[i] > sub {
ok := true
for k, t := range arr {
if k != i && strings.Contains(t, sub) {
ok = false
break
}
}
if ok {
ans[i] = sub
}
}
}
}
}
return ans
}
```

```ts
function shortestSubstrings(arr: string[]): string[] {
const n: number = arr.length;
const ans: string[] = Array(n).fill('');
for (let i = 0; i < n; ++i) {
const m: number = arr[i].length;
for (let j = 1; j <= m && ans[i] === ''; ++j) {
for (let l = 0; l <= m - j; ++l) {
const sub: string = arr[i].slice(l, l + j);
if (ans[i] === '' || sub.localeCompare(ans[i]) < 0) {
let ok: boolean = true;
for (let k = 0; k < n && ok; ++k) {
if (k !== i && arr[k].includes(sub)) {
ok = false;
}
}
if (ok) {
ans[i] = sub;
}
}
}
}
}
return ans;
}
```

<!-- tabs:end -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Solution {
public:
vector<string> shortestSubstrings(vector<string>& arr) {
int n = arr.size();
vector<string> ans(n);
for (int i = 0; i < n; ++i) {
int m = arr[i].size();
for (int j = 1; j <= m && ans[i].empty(); ++j) {
for (int l = 0; l <= m - j; ++l) {
string sub = arr[i].substr(l, j);
if (ans[i].empty() || sub < ans[i]) {
bool ok = true;
for (int k = 0; k < n && ok; ++k) {
if (k != i && arr[k].find(sub) != string::npos) {
ok = false;
}
}
if (ok) {
ans[i] = sub;
}
}
}
}
}
return ans;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
func shortestSubstrings(arr []string) []string {
ans := make([]string, len(arr))
for i, s := range arr {
m := len(s)
for j := 1; j <= m && len(ans[i]) == 0; j++ {
for l := 0; l <= m-j; l++ {
sub := s[l : l+j]
if len(ans[i]) == 0 || ans[i] > sub {
ok := true
for k, t := range arr {
if k != i && strings.Contains(t, sub) {
ok = false
break
}
}
if ok {
ans[i] = sub
}
}
}
}
}
return ans
}
Loading
Loading