Skip to content

Commit 01faba5

Browse files
committed
feat: add solutions to lcci problem: No.17.26
No.17.26.Sparse Similarity
1 parent 0f1860d commit 01faba5

File tree

6 files changed

+366
-3
lines changed

6 files changed

+366
-3
lines changed

lcci/17.26.Sparse Similarity/README.md

+137-2
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,154 @@
2727
<li><code>docs[i].length &lt;= 500</code></li>
2828
<li>相似度大于 0 的文档对数不会超过 1000</li>
2929
</ul>
30+
3031
## 解法
32+
3133
<!-- 这里可写通用的实现逻辑 -->
34+
35+
**方法一:哈希表**
36+
37+
用哈希表 $d$ 记录每个单词对应了哪些文档。
38+
39+
遍历 $d$ 的每一个文档列表,其任意两个文档都有相似度,我们用哈希表 $s$ 累加两个文档同时出现的单词个数。最后遍历 $s$,计算相似度。
40+
41+
时间复杂度 $O(n^3)$。
42+
3243
<!-- tabs:start -->
44+
3345
### **Python3**
46+
3447
<!-- 这里可写当前语言的特殊实现逻辑 -->
48+
3549
```python
50+
class Solution:
51+
def computeSimilarities(self, docs: List[List[int]]) -> List[str]:
52+
eps = 1e-9
53+
d = defaultdict(list)
54+
for i, v in enumerate(docs):
55+
for x in v:
56+
d[x].append(i)
57+
cnt = Counter()
58+
for ids in d.values():
59+
n = len(ids)
60+
for i in range(n):
61+
for j in range(i + 1, n):
62+
cnt[(ids[i], ids[j])] += 1
63+
ans = []
64+
for (i, j), v in cnt.items():
65+
tot = len(docs[i]) + len(docs[j]) - v
66+
x = v / tot + eps
67+
ans.append(f'{i},{j}: {x:.4f}')
68+
return ans
69+
```
3670

37-
````
3871
### **Java**
72+
3973
<!-- 这里可写当前语言的特殊实现逻辑 -->
74+
4075
```java
76+
class Solution {
77+
public List<String> computeSimilarities(int[][] docs) {
78+
Map<Integer, List<Integer>> d = new HashMap<>();
79+
for (int i = 0; i < docs.length; ++i) {
80+
for (int v : docs[i]) {
81+
d.computeIfAbsent(v, k -> new ArrayList<>()).add(i);
82+
}
83+
}
84+
Map<String, Integer> cnt = new HashMap<>();
85+
for (var ids : d.values()) {
86+
int n = ids.size();
87+
for (int i = 0; i < n; ++i) {
88+
for (int j = i + 1; j < n; ++j) {
89+
String k = ids.get(i) + "," + ids.get(j);
90+
cnt.put(k, cnt.getOrDefault(k, 0) + 1);
91+
}
92+
}
93+
}
94+
List<String> ans = new ArrayList<>();
95+
for (var e : cnt.entrySet()) {
96+
String k = e.getKey();
97+
int v = e.getValue();
98+
String[] t = k.split(",");
99+
int i = Integer.parseInt(t[0]), j = Integer.parseInt(t[1]);
100+
int tot = docs[i].length + docs[j].length - v;
101+
double x = (double) v / tot;
102+
ans.add(String.format("%s: %.4f", k, x));
103+
}
104+
return ans;
105+
}
106+
}
107+
```
108+
109+
### **C++**
41110

42-
````
111+
```cpp
112+
using pii = pair<int, int>;
113+
114+
class Solution {
115+
public:
116+
vector<string> computeSimilarities(vector<vector<int>>& docs) {
117+
double eps = 1e-9;
118+
unordered_map<int, vector<int>> d;
119+
for (int i = 0; i < docs.size(); ++i) {
120+
for (int v : docs[i]) {
121+
d[v].push_back(i);
122+
}
123+
}
124+
map<pii, int> cnt;
125+
for (auto& [_, ids] : d) {
126+
int n = ids.size();
127+
for (int i = 0; i < n; ++i) {
128+
for (int j = i + 1; j < n; ++j) {
129+
cnt[{ids[i], ids[j]}]++;
130+
}
131+
}
132+
}
133+
vector<string> ans;
134+
for (auto& [k, v] : cnt) {
135+
auto [i, j] = k;
136+
int tot = docs[i].size() + docs[j].size() - v;
137+
double x = (double) v / tot + eps;
138+
char t[20];
139+
sprintf(t, "%d,%d: %0.4lf", i, j, x);
140+
ans.push_back(t);
141+
}
142+
return ans;
143+
}
144+
};
145+
```
146+
147+
### **Go**
148+
149+
```go
150+
func computeSimilarities(docs [][]int) []string {
151+
d := map[int][]int{}
152+
for i, v := range docs {
153+
for _, x := range v {
154+
d[x] = append(d[x], i)
155+
}
156+
}
157+
type pair struct{ i, j int }
158+
cnt := map[pair]int{}
159+
for _, ids := range d {
160+
n := len(ids)
161+
for i := 0; i < n; i++ {
162+
for j := i + 1; j < n; j++ {
163+
k := pair{ids[i], ids[j]}
164+
cnt[k]++
165+
}
166+
}
167+
}
168+
ans := []string{}
169+
for k, v := range cnt {
170+
i, j := k.i, k.j
171+
tot := len(docs[i]) + len(docs[j]) - v
172+
x := float64(v)/float64(tot) + 1e-9
173+
ans = append(ans, strconv.Itoa(i)+","+strconv.Itoa(j)+": "+fmt.Sprintf("%.4f", x))
174+
}
175+
return ans
176+
}
177+
```
43178

44179
### **...**
45180

lcci/17.26.Sparse Similarity/README_EN.md

+119-1
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,131 @@
4949
### **Python3**
5050

5151
```python
52-
52+
class Solution:
53+
def computeSimilarities(self, docs: List[List[int]]) -> List[str]:
54+
eps = 1e-9
55+
d = defaultdict(list)
56+
for i, v in enumerate(docs):
57+
for x in v:
58+
d[x].append(i)
59+
cnt = Counter()
60+
for ids in d.values():
61+
n = len(ids)
62+
for i in range(n):
63+
for j in range(i + 1, n):
64+
cnt[(ids[i], ids[j])] += 1
65+
ans = []
66+
for (i, j), v in cnt.items():
67+
tot = len(docs[i]) + len(docs[j]) - v
68+
x = v / tot + eps
69+
ans.append(f'{i},{j}: {x:.4f}')
70+
return ans
5371
```
5472

5573
### **Java**
5674

5775
```java
76+
class Solution {
77+
public List<String> computeSimilarities(int[][] docs) {
78+
Map<Integer, List<Integer>> d = new HashMap<>();
79+
for (int i = 0; i < docs.length; ++i) {
80+
for (int v : docs[i]) {
81+
d.computeIfAbsent(v, k -> new ArrayList<>()).add(i);
82+
}
83+
}
84+
Map<String, Integer> cnt = new HashMap<>();
85+
for (var ids : d.values()) {
86+
int n = ids.size();
87+
for (int i = 0; i < n; ++i) {
88+
for (int j = i + 1; j < n; ++j) {
89+
String k = ids.get(i) + "," + ids.get(j);
90+
cnt.put(k, cnt.getOrDefault(k, 0) + 1);
91+
}
92+
}
93+
}
94+
List<String> ans = new ArrayList<>();
95+
for (var e : cnt.entrySet()) {
96+
String k = e.getKey();
97+
int v = e.getValue();
98+
String[] t = k.split(",");
99+
int i = Integer.parseInt(t[0]), j = Integer.parseInt(t[1]);
100+
int tot = docs[i].length + docs[j].length - v;
101+
double x = (double) v / tot;
102+
ans.add(String.format("%s: %.4f", k, x));
103+
}
104+
return ans;
105+
}
106+
}
107+
```
108+
109+
### **C++**
110+
111+
```cpp
112+
using pii = pair<int, int>;
113+
114+
class Solution {
115+
public:
116+
vector<string> computeSimilarities(vector<vector<int>>& docs) {
117+
double eps = 1e-9;
118+
unordered_map<int, vector<int>> d;
119+
for (int i = 0; i < docs.size(); ++i) {
120+
for (int v : docs[i]) {
121+
d[v].push_back(i);
122+
}
123+
}
124+
map<pii, int> cnt;
125+
for (auto& [_, ids] : d) {
126+
int n = ids.size();
127+
for (int i = 0; i < n; ++i) {
128+
for (int j = i + 1; j < n; ++j) {
129+
cnt[{ids[i], ids[j]}]++;
130+
}
131+
}
132+
}
133+
vector<string> ans;
134+
for (auto& [k, v] : cnt) {
135+
auto [i, j] = k;
136+
int tot = docs[i].size() + docs[j].size() - v;
137+
double x = (double) v / tot + eps;
138+
char t[20];
139+
sprintf(t, "%d,%d: %0.4lf", i, j, x);
140+
ans.push_back(t);
141+
}
142+
return ans;
143+
}
144+
};
145+
```
58146
147+
### **Go**
148+
149+
```go
150+
func computeSimilarities(docs [][]int) []string {
151+
d := map[int][]int{}
152+
for i, v := range docs {
153+
for _, x := range v {
154+
d[x] = append(d[x], i)
155+
}
156+
}
157+
type pair struct{ i, j int }
158+
cnt := map[pair]int{}
159+
for _, ids := range d {
160+
n := len(ids)
161+
for i := 0; i < n; i++ {
162+
for j := i + 1; j < n; j++ {
163+
k := pair{ids[i], ids[j]}
164+
cnt[k]++
165+
}
166+
}
167+
}
168+
ans := []string{}
169+
for k, v := range cnt {
170+
i, j := k.i, k.j
171+
tot := len(docs[i]) + len(docs[j]) - v
172+
x := float64(v)/float64(tot) + 1e-9
173+
ans = append(ans, strconv.Itoa(i)+","+strconv.Itoa(j)+": "+fmt.Sprintf("%.4f", x))
174+
}
175+
return ans
176+
}
59177
```
60178

61179
### **...**
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using pii = pair<int, int>;
2+
3+
class Solution {
4+
public:
5+
vector<string> computeSimilarities(vector<vector<int>>& docs) {
6+
double eps = 1e-9;
7+
unordered_map<int, vector<int>> d;
8+
for (int i = 0; i < docs.size(); ++i) {
9+
for (int v : docs[i]) {
10+
d[v].push_back(i);
11+
}
12+
}
13+
map<pii, int> cnt;
14+
for (auto& [_, ids] : d) {
15+
int n = ids.size();
16+
for (int i = 0; i < n; ++i) {
17+
for (int j = i + 1; j < n; ++j) {
18+
cnt[{ids[i], ids[j]}]++;
19+
}
20+
}
21+
}
22+
vector<string> ans;
23+
for (auto& [k, v] : cnt) {
24+
auto [i, j] = k;
25+
int tot = docs[i].size() + docs[j].size() - v;
26+
double x = (double) v / tot + eps;
27+
char t[20];
28+
sprintf(t, "%d,%d: %0.4lf", i, j, x);
29+
ans.push_back(t);
30+
}
31+
return ans;
32+
}
33+
};
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
func computeSimilarities(docs [][]int) []string {
2+
d := map[int][]int{}
3+
for i, v := range docs {
4+
for _, x := range v {
5+
d[x] = append(d[x], i)
6+
}
7+
}
8+
type pair struct{ i, j int }
9+
cnt := map[pair]int{}
10+
for _, ids := range d {
11+
n := len(ids)
12+
for i := 0; i < n; i++ {
13+
for j := i + 1; j < n; j++ {
14+
k := pair{ids[i], ids[j]}
15+
cnt[k]++
16+
}
17+
}
18+
}
19+
ans := []string{}
20+
for k, v := range cnt {
21+
i, j := k.i, k.j
22+
tot := len(docs[i]) + len(docs[j]) - v
23+
x := float64(v)/float64(tot) + 1e-9
24+
ans = append(ans, strconv.Itoa(i)+","+strconv.Itoa(j)+": "+fmt.Sprintf("%.4f", x))
25+
}
26+
return ans
27+
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class Solution {
2+
public List<String> computeSimilarities(int[][] docs) {
3+
Map<Integer, List<Integer>> d = new HashMap<>();
4+
for (int i = 0; i < docs.length; ++i) {
5+
for (int v : docs[i]) {
6+
d.computeIfAbsent(v, k -> new ArrayList<>()).add(i);
7+
}
8+
}
9+
Map<String, Integer> cnt = new HashMap<>();
10+
for (var ids : d.values()) {
11+
int n = ids.size();
12+
for (int i = 0; i < n; ++i) {
13+
for (int j = i + 1; j < n; ++j) {
14+
String k = ids.get(i) + "," + ids.get(j);
15+
cnt.put(k, cnt.getOrDefault(k, 0) + 1);
16+
}
17+
}
18+
}
19+
List<String> ans = new ArrayList<>();
20+
for (var e : cnt.entrySet()) {
21+
String k = e.getKey();
22+
int v = e.getValue();
23+
String[] t = k.split(",");
24+
int i = Integer.parseInt(t[0]), j = Integer.parseInt(t[1]);
25+
int tot = docs[i].length + docs[j].length - v;
26+
double x = (double) v / tot;
27+
ans.add(String.format("%s: %.4f", k, x));
28+
}
29+
return ans;
30+
}
31+
}

0 commit comments

Comments
 (0)