feat: add solutions to lc problem: No.0734 (#4025)

No.0734.Sentence Similarity
This commit is contained in:
Libin YANG 2025-02-05 12:52:48 +08:00 committed by GitHub
parent 705fcd39c8
commit b901bf832b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 355 additions and 68 deletions

View File

@ -63,7 +63,13 @@ myCalendar.book(20, 30); // return True, The event can be booked, as the first e
<!-- solution:start -->
### Solution 1
### Solution 1: Ordered Set
We can use an ordered set to store the schedule. An ordered set can perform insert, delete, and search operations in $O(\log n)$ time. The elements in the ordered set are sorted by the $\textit{endTime}$ of the schedule in ascending order.
When calling the $\text{book}(start, end)$ method, we search for the first schedule in the ordered set with an end time greater than $\textit{start}$. If it exists and its start time is less than $\textit{end}$, it means there is a double booking, and we return $\text{false}$. Otherwise, we insert $\textit{end}$ as the key and $\textit{start}$ as the value into the ordered set and return $\text{true}$.
The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of schedules.
<!-- tabs:start -->

View File

@ -80,6 +80,16 @@ tags:
### 方法一:哈希表
我们首先判断 $\textit{sentence1}$ 和 $\textit{sentence2}$ 的长度是否相等,如果不相等则返回 $\text{false}$。
然后我们使用一个哈希表 $\textit{s}$ 来存储所有相似的单词对,对于 $\textit{similarPairs}$ 中的每一个单词对 $[x, y]$,我们将 $x$ 和 $y$ 加入到哈希表 $\textit{s}$ 中。
接下来我们遍历 $\textit{sentence1}$ 和 $\textit{sentence2}$,对于每一个位置 $i$,如果 $\textit{sentence1}[i]$ 不等于 $\textit{sentence2}[i]$,并且 $(\textit{sentence1}[i], \textit{sentence2}[i])$ 和 $(\textit{sentence2}[i], \textit{sentence1}[i])$ 都不在哈希表 $\textit{s}$ 中,那么返回 $\text{false}$。
如果遍历结束后都没有返回 $\text{false}$,说明 $\textit{sentence1}$ 和 $\textit{sentence2}$ 是相似的,返回 $\text{true}$。
时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 为题目中所有字符串的长度之和。
<!-- tabs:start -->
#### Python3
@ -91,10 +101,11 @@ class Solution:
) -> bool:
if len(sentence1) != len(sentence2):
return False
s = {(a, b) for a, b in similarPairs}
return all(
a == b or (a, b) in s or (b, a) in s for a, b in zip(sentence1, sentence2)
)
s = {(x, y) for x, y in similarPairs}
for x, y in zip(sentence1, sentence2):
if x != y and (x, y) not in s and (y, x) not in s:
return False
return True
```
#### Java
@ -106,13 +117,14 @@ class Solution {
if (sentence1.length != sentence2.length) {
return false;
}
Set<String> s = new HashSet<>();
for (List<String> e : similarPairs) {
s.add(e.get(0) + "." + e.get(1));
Set<List<String>> s = new HashSet<>();
for (var p : similarPairs) {
s.add(p);
}
for (int i = 0; i < sentence1.length; ++i) {
String a = sentence1[i], b = sentence2[i];
if (!a.equals(b) && !s.contains(a + "." + b) && !s.contains(b + "." + a)) {
for (int i = 0; i < sentence1.length; i++) {
if (!sentence1[i].equals(sentence2[i])
&& !s.contains(List.of(sentence1[i], sentence2[i]))
&& !s.contains(List.of(sentence2[i], sentence1[i]))) {
return false;
}
}
@ -127,13 +139,18 @@ class Solution {
class Solution {
public:
bool areSentencesSimilar(vector<string>& sentence1, vector<string>& sentence2, vector<vector<string>>& similarPairs) {
int m = sentence1.size(), n = sentence2.size();
if (m != n) return false;
if (sentence1.size() != sentence2.size()) {
return false;
}
unordered_set<string> s;
for (auto e : similarPairs) s.insert(e[0] + "." + e[1]);
for (int i = 0; i < n; ++i) {
string a = sentence1[i], b = sentence2[i];
if (a != b && !s.count(a + "." + b) && !s.count(b + "." + a)) return false;
for (const auto& p : similarPairs) {
s.insert(p[0] + "#" + p[1]);
s.insert(p[1] + "#" + p[0]);
}
for (int i = 0; i < sentence1.size(); ++i) {
if (sentence1[i] != sentence2[i] && !s.contains(sentence1[i] + "#" + sentence2[i])) {
return false;
}
}
return true;
}
@ -148,12 +165,12 @@ func areSentencesSimilar(sentence1 []string, sentence2 []string, similarPairs []
return false
}
s := map[string]bool{}
for _, e := range similarPairs {
s[e[0]+"."+e[1]] = true
for _, p := range similarPairs {
s[p[0]+"#"+p[1]] = true
}
for i, a := range sentence1 {
b := sentence2[i]
if a != b && !s[a+"."+b] && !s[b+"."+a] {
for i, x := range sentence1 {
y := sentence2[i]
if x != y && !s[x+"#"+y] && !s[y+"#"+x] {
return false
}
}
@ -161,6 +178,91 @@ func areSentencesSimilar(sentence1 []string, sentence2 []string, similarPairs []
}
```
#### TypeScript
```ts
function areSentencesSimilar(
sentence1: string[],
sentence2: string[],
similarPairs: string[][],
): boolean {
if (sentence1.length !== sentence2.length) {
return false;
}
const s = new Set<string>();
for (const [x, y] of similarPairs) {
s.add(x + '#' + y);
s.add(y + '#' + x);
}
for (let i = 0; i < sentence1.length; i++) {
if (sentence1[i] !== sentence2[i] && !s.has(sentence1[i] + '#' + sentence2[i])) {
return false;
}
}
return true;
}
```
#### Rust
```rust
use std::collections::HashSet;
impl Solution {
pub fn are_sentences_similar(
sentence1: Vec<String>,
sentence2: Vec<String>,
similar_pairs: Vec<Vec<String>>,
) -> bool {
if sentence1.len() != sentence2.len() {
return false;
}
let s: HashSet<(String, String)> = similar_pairs
.into_iter()
.map(|pair| (pair[0].clone(), pair[1].clone()))
.collect();
for (x, y) in sentence1.iter().zip(sentence2.iter()) {
if x != y
&& !s.contains(&(x.clone(), y.clone()))
&& !s.contains(&(y.clone(), x.clone()))
{
return false;
}
}
true
}
}
```
#### JavaScript
```js
/**
* @param {string[]} sentence1
* @param {string[]} sentence2
* @param {string[][]} similarPairs
* @return {boolean}
*/
var areSentencesSimilar = function (sentence1, sentence2, similarPairs) {
if (sentence1.length !== sentence2.length) {
return false;
}
const s = new Set();
for (const [x, y] of similarPairs) {
s.add(x + '#' + y);
s.add(y + '#' + x);
}
for (let i = 0; i < sentence1.length; i++) {
if (sentence1[i] !== sentence2[i] && !s.has(sentence1[i] + '#' + sentence2[i])) {
return false;
}
}
return true;
};
```
<!-- tabs:end -->
<!-- solution:end -->

View File

@ -78,7 +78,17 @@ tags:
<!-- solution:start -->
### Solution 1
### Solution 1: Hash Table
First, we check if the lengths of $\textit{sentence1}$ and $\textit{sentence2}$ are equal. If they are not equal, return $\text{false}$.
Then we use a hash table $\textit{s}$ to store all similar word pairs. For each word pair $[x, y]$ in $\textit{similarPairs}$, we add $x$ and $y$ to the hash table $\textit{s}$.
Next, we traverse $\textit{sentence1}$ and $\textit{sentence2}$. For each position $i$, if $\textit{sentence1}[i]$ is not equal to $\textit{sentence2}[i]$, and $(\textit{sentence1}[i], \textit{sentence2}[i])$ and $(\textit{sentence2}[i], \textit{sentence1}[i])$ are not in the hash table $\textit{s}$, then return $\text{false}$.
If the traversal ends without returning $\text{false}$, it means $\textit{sentence1}$ and $\textit{sentence2}$ are similar, so return $\text{true}$.
The time complexity is $O(L)$, and the space complexity is $O(L)$, where $L$ is the sum of the lengths of all strings in the problem.
<!-- tabs:start -->
@ -91,10 +101,11 @@ class Solution:
) -> bool:
if len(sentence1) != len(sentence2):
return False
s = {(a, b) for a, b in similarPairs}
return all(
a == b or (a, b) in s or (b, a) in s for a, b in zip(sentence1, sentence2)
)
s = {(x, y) for x, y in similarPairs}
for x, y in zip(sentence1, sentence2):
if x != y and (x, y) not in s and (y, x) not in s:
return False
return True
```
#### Java
@ -106,13 +117,14 @@ class Solution {
if (sentence1.length != sentence2.length) {
return false;
}
Set<String> s = new HashSet<>();
for (List<String> e : similarPairs) {
s.add(e.get(0) + "." + e.get(1));
Set<List<String>> s = new HashSet<>();
for (var p : similarPairs) {
s.add(p);
}
for (int i = 0; i < sentence1.length; ++i) {
String a = sentence1[i], b = sentence2[i];
if (!a.equals(b) && !s.contains(a + "." + b) && !s.contains(b + "." + a)) {
for (int i = 0; i < sentence1.length; i++) {
if (!sentence1[i].equals(sentence2[i])
&& !s.contains(List.of(sentence1[i], sentence2[i]))
&& !s.contains(List.of(sentence2[i], sentence1[i]))) {
return false;
}
}
@ -127,13 +139,18 @@ class Solution {
class Solution {
public:
bool areSentencesSimilar(vector<string>& sentence1, vector<string>& sentence2, vector<vector<string>>& similarPairs) {
int m = sentence1.size(), n = sentence2.size();
if (m != n) return false;
if (sentence1.size() != sentence2.size()) {
return false;
}
unordered_set<string> s;
for (auto e : similarPairs) s.insert(e[0] + "." + e[1]);
for (int i = 0; i < n; ++i) {
string a = sentence1[i], b = sentence2[i];
if (a != b && !s.count(a + "." + b) && !s.count(b + "." + a)) return false;
for (const auto& p : similarPairs) {
s.insert(p[0] + "#" + p[1]);
s.insert(p[1] + "#" + p[0]);
}
for (int i = 0; i < sentence1.size(); ++i) {
if (sentence1[i] != sentence2[i] && !s.contains(sentence1[i] + "#" + sentence2[i])) {
return false;
}
}
return true;
}
@ -148,12 +165,12 @@ func areSentencesSimilar(sentence1 []string, sentence2 []string, similarPairs []
return false
}
s := map[string]bool{}
for _, e := range similarPairs {
s[e[0]+"."+e[1]] = true
for _, p := range similarPairs {
s[p[0]+"#"+p[1]] = true
}
for i, a := range sentence1 {
b := sentence2[i]
if a != b && !s[a+"."+b] && !s[b+"."+a] {
for i, x := range sentence1 {
y := sentence2[i]
if x != y && !s[x+"#"+y] && !s[y+"#"+x] {
return false
}
}
@ -161,6 +178,91 @@ func areSentencesSimilar(sentence1 []string, sentence2 []string, similarPairs []
}
```
#### TypeScript
```ts
function areSentencesSimilar(
sentence1: string[],
sentence2: string[],
similarPairs: string[][],
): boolean {
if (sentence1.length !== sentence2.length) {
return false;
}
const s = new Set<string>();
for (const [x, y] of similarPairs) {
s.add(x + '#' + y);
s.add(y + '#' + x);
}
for (let i = 0; i < sentence1.length; i++) {
if (sentence1[i] !== sentence2[i] && !s.has(sentence1[i] + '#' + sentence2[i])) {
return false;
}
}
return true;
}
```
#### Rust
```rust
use std::collections::HashSet;
impl Solution {
pub fn are_sentences_similar(
sentence1: Vec<String>,
sentence2: Vec<String>,
similar_pairs: Vec<Vec<String>>,
) -> bool {
if sentence1.len() != sentence2.len() {
return false;
}
let s: HashSet<(String, String)> = similar_pairs
.into_iter()
.map(|pair| (pair[0].clone(), pair[1].clone()))
.collect();
for (x, y) in sentence1.iter().zip(sentence2.iter()) {
if x != y
&& !s.contains(&(x.clone(), y.clone()))
&& !s.contains(&(y.clone(), x.clone()))
{
return false;
}
}
true
}
}
```
#### JavaScript
```js
/**
* @param {string[]} sentence1
* @param {string[]} sentence2
* @param {string[][]} similarPairs
* @return {boolean}
*/
var areSentencesSimilar = function (sentence1, sentence2, similarPairs) {
if (sentence1.length !== sentence2.length) {
return false;
}
const s = new Set();
for (const [x, y] of similarPairs) {
s.add(x + '#' + y);
s.add(y + '#' + x);
}
for (let i = 0; i < sentence1.length; i++) {
if (sentence1[i] !== sentence2[i] && !s.has(sentence1[i] + '#' + sentence2[i])) {
return false;
}
}
return true;
};
```
<!-- tabs:end -->
<!-- solution:end -->

View File

@ -1,14 +1,19 @@
class Solution {
public:
bool areSentencesSimilar(vector<string>& sentence1, vector<string>& sentence2, vector<vector<string>>& similarPairs) {
int m = sentence1.size(), n = sentence2.size();
if (m != n) return false;
if (sentence1.size() != sentence2.size()) {
return false;
}
unordered_set<string> s;
for (auto e : similarPairs) s.insert(e[0] + "." + e[1]);
for (int i = 0; i < n; ++i) {
string a = sentence1[i], b = sentence2[i];
if (a != b && !s.count(a + "." + b) && !s.count(b + "." + a)) return false;
for (const auto& p : similarPairs) {
s.insert(p[0] + "#" + p[1]);
s.insert(p[1] + "#" + p[0]);
}
for (int i = 0; i < sentence1.size(); ++i) {
if (sentence1[i] != sentence2[i] && !s.contains(sentence1[i] + "#" + sentence2[i])) {
return false;
}
}
return true;
}
};
};

View File

@ -3,14 +3,14 @@ func areSentencesSimilar(sentence1 []string, sentence2 []string, similarPairs []
return false
}
s := map[string]bool{}
for _, e := range similarPairs {
s[e[0]+"."+e[1]] = true
for _, p := range similarPairs {
s[p[0]+"#"+p[1]] = true
}
for i, a := range sentence1 {
b := sentence2[i]
if a != b && !s[a+"."+b] && !s[b+"."+a] {
for i, x := range sentence1 {
y := sentence2[i]
if x != y && !s[x+"#"+y] && !s[y+"#"+x] {
return false
}
}
return true
}
}

View File

@ -4,16 +4,17 @@ class Solution {
if (sentence1.length != sentence2.length) {
return false;
}
Set<String> s = new HashSet<>();
for (List<String> e : similarPairs) {
s.add(e.get(0) + "." + e.get(1));
Set<List<String>> s = new HashSet<>();
for (var p : similarPairs) {
s.add(p);
}
for (int i = 0; i < sentence1.length; ++i) {
String a = sentence1[i], b = sentence2[i];
if (!a.equals(b) && !s.contains(a + "." + b) && !s.contains(b + "." + a)) {
for (int i = 0; i < sentence1.length; i++) {
if (!sentence1[i].equals(sentence2[i])
&& !s.contains(List.of(sentence1[i], sentence2[i]))
&& !s.contains(List.of(sentence2[i], sentence1[i]))) {
return false;
}
}
return true;
}
}
}

View File

@ -0,0 +1,22 @@
/**
* @param {string[]} sentence1
* @param {string[]} sentence2
* @param {string[][]} similarPairs
* @return {boolean}
*/
var areSentencesSimilar = function (sentence1, sentence2, similarPairs) {
if (sentence1.length !== sentence2.length) {
return false;
}
const s = new Set();
for (const [x, y] of similarPairs) {
s.add(x + '#' + y);
s.add(y + '#' + x);
}
for (let i = 0; i < sentence1.length; i++) {
if (sentence1[i] !== sentence2[i] && !s.has(sentence1[i] + '#' + sentence2[i])) {
return false;
}
}
return true;
};

View File

@ -4,7 +4,8 @@ class Solution:
) -> bool:
if len(sentence1) != len(sentence2):
return False
s = {(a, b) for a, b in similarPairs}
return all(
a == b or (a, b) in s or (b, a) in s for a, b in zip(sentence1, sentence2)
)
s = {(x, y) for x, y in similarPairs}
for x, y in zip(sentence1, sentence2):
if x != y and (x, y) not in s and (y, x) not in s:
return False
return True

View File

@ -0,0 +1,28 @@
use std::collections::HashSet;
impl Solution {
pub fn are_sentences_similar(
sentence1: Vec<String>,
sentence2: Vec<String>,
similar_pairs: Vec<Vec<String>>,
) -> bool {
if sentence1.len() != sentence2.len() {
return false;
}
let s: HashSet<(String, String)> = similar_pairs
.into_iter()
.map(|pair| (pair[0].clone(), pair[1].clone()))
.collect();
for (x, y) in sentence1.iter().zip(sentence2.iter()) {
if x != y
&& !s.contains(&(x.clone(), y.clone()))
&& !s.contains(&(y.clone(), x.clone()))
{
return false;
}
}
true
}
}

View File

@ -0,0 +1,20 @@
function areSentencesSimilar(
sentence1: string[],
sentence2: string[],
similarPairs: string[][],
): boolean {
if (sentence1.length !== sentence2.length) {
return false;
}
const s = new Set<string>();
for (const [x, y] of similarPairs) {
s.add(x + '#' + y);
s.add(y + '#' + x);
}
for (let i = 0; i < sentence1.length; i++) {
if (sentence1[i] !== sentence2[i] && !s.has(sentence1[i] + '#' + sentence2[i])) {
return false;
}
}
return true;
}