43
43
44
44
## 解法
45
45
46
- ** 方法一:哈希表**
46
+ ** 方法一:哈希表 + 枚举二的幂 **
47
47
48
- 用最暴力的方法枚举每对元素肯定会超时,可以用哈希表优化对 ** 之前元素出现次数 ** 的查询 。
48
+ 根据题意,我们需要统计数组中两个数的和为 $2$ 的幂的组合数。直接暴力枚举所有的组合数,时间复杂度为 $O(n^2)$ ,肯定会超时 。
49
49
50
- ** 方法二:枚举二的幂 **
50
+ 我们可以遍历数组,用哈希表 $cnt$ 维护数组中每个元素 $d$ 出现的次数。
51
51
52
- 用哈希表 ` cnt ` 记录数组中每个元素出现的次数 。
52
+ 对于每个元素,我们从小到大枚举二的幂次方 $s$ 作为两数之和,将哈希表中 $s - d$ 出现的次数累加到答案中。然后将当前元素 $d$ 出现的次数加一 。
53
53
54
- 枚举二的幂次方作为两数之和 ` s ` ,然后枚举其中一个数 ` a ` ,判断 ` s-a ` 是否出现在哈希表 ` cnt ` 中。若出现,判断 ` a ` 与 ` b ` 是否相等,是则答案累加 ` cnt[a] * (cnt[a]-1) ` ,否则答案累加 ` cnt[a] * cnt[b] ` 。
54
+ 遍历结束后,返回答案即可 。
55
55
56
- 由于每个 ` a ` , ` b ` 会重复枚举,因此最后答案需要除以 ` 2 ` 。注意取模操作 。
56
+ 时间复杂度 $O(n\times \log M)$,其中 $n$ 是数组 ` deliciousness ` 的长度,而 $M$ 是元素的上限,对于本题,上限 $M=2^{20}$ 。
57
57
58
- 时间复杂度 $O(n\log C)$,其中 $n$ 是数组 ` deliciousness ` 的长度,而 $C$ 是元素的上限,对于本题,上限 $C=2^{20}$。
58
+ 我们也可以先用哈希表 $cnt$ 统计数组中每个元素出现的次数。
59
+
60
+ 然后从小到大枚举二的幂次方 $s$ 作为两数之和,对于每个 $s$,遍历哈希表每个键值对 $(a, m)$,如果 $s - a$ 也在哈希表中,且 $s - a \neq a$,则答案加上 $m \times cnt[ s - a] $;如果 $s - a = a$,则答案加上 $m \times (m - 1)$。
61
+
62
+ 最后,将答案除以 $2$ 之后,模 $10^9 + 7$,返回即可。
63
+
64
+ 时间复杂度与上面的方法相同。
59
65
60
66
<!-- 这里可写通用的实现逻辑 -->
61
67
68
74
``` python
69
75
class Solution :
70
76
def countPairs (self , deliciousness : List[int ]) -> int :
71
- mod = 1000000007
72
- limit = max (deliciousness) * 2
73
- pairs = 0
74
- freq = defaultdict( int )
77
+ mod = 10 ** 9 + 7
78
+ mx = max (deliciousness) << 1
79
+ cnt = Counter()
80
+ ans = 0
75
81
for d in deliciousness:
76
- target = 1
77
- while target <= limit :
78
- pairs = (pairs + freq[target - d]) % mod
79
- target = target << 1
80
- freq [d] += 1
81
- return pairs
82
+ s = 1
83
+ while s <= mx :
84
+ ans = (ans + cnt[s - d]) % mod
85
+ s <<= 1
86
+ cnt [d] += 1
87
+ return ans
82
88
```
83
89
84
90
``` python
85
91
class Solution :
86
92
def countPairs (self , deliciousness : List[int ]) -> int :
93
+ mod = 10 ** 9 + 7
87
94
cnt = Counter(deliciousness)
88
95
ans = 0
89
- mod = 10 ** 9 + 7
90
96
for i in range (22 ):
91
97
s = 1 << i
92
98
for a, m in cnt.items():
93
99
if (b := s - a) in cnt:
94
- if a == b:
95
- ans += m * (m - 1 )
96
- else :
97
- ans += m * cnt[b]
100
+ ans += m * (m - 1 ) if a == b else m * cnt[b]
98
101
return (ans >> 1 ) % mod
99
102
```
100
103
@@ -104,21 +107,19 @@ class Solution:
104
107
105
108
``` java
106
109
class Solution {
107
-
108
- private static final int MOD = 1000000007 ;
110
+ private static final int MOD = (int ) 1e9 + 7 ;
109
111
110
112
public int countPairs (int [] deliciousness ) {
111
- int limit = Arrays . stream(deliciousness). max(). getAsInt() * 2 ;
112
- int pairs = 0 ;
113
- Map<Integer , Integer > freq = new HashMap<> ();
113
+ int mx = Arrays . stream(deliciousness). max(). getAsInt() << 1 ;
114
+ int ans = 0 ;
115
+ Map<Integer , Integer > cnt = new HashMap<> ();
114
116
for (int d : deliciousness) {
115
- for (int sum = 1 ; sum <= limit; sum << = 1 ) {
116
- int count = freq. getOrDefault(sum - d, 0 );
117
- pairs = (pairs + count) % MOD ;
117
+ for (int s = 1 ; s <= mx; s << = 1 ) {
118
+ ans = (ans + cnt. getOrDefault(s - d, 0 )) % MOD ;
118
119
}
119
- freq . merge(d, 1 , Integer :: sum);
120
+ cnt . merge(d, 1 , Integer :: sum);
120
121
}
121
- return pairs ;
122
+ return ans ;
122
123
}
123
124
}
124
125
```
@@ -129,8 +130,8 @@ class Solution {
129
130
130
131
public int countPairs (int [] deliciousness ) {
131
132
Map<Integer , Integer > cnt = new HashMap<> ();
132
- for (int v : deliciousness) {
133
- cnt. put(v , cnt. getOrDefault(v , 0 ) + 1 );
133
+ for (int d : deliciousness) {
134
+ cnt. put(d , cnt. getOrDefault(d , 0 ) + 1 );
134
135
}
135
136
long ans = 0 ;
136
137
for (int i = 0 ; i < 22 ; ++ i) {
@@ -141,11 +142,7 @@ class Solution {
141
142
if (! cnt. containsKey(b)) {
142
143
continue ;
143
144
}
144
- if (a == b) {
145
- ans += (long ) m * (m - 1 );
146
- } else {
147
- ans += (long ) m * cnt. get(b);
148
- }
145
+ ans += 1L * m * (a == b ? m - 1 : cnt. get(b));
149
146
}
150
147
}
151
148
ans >> = 1 ;
@@ -154,87 +151,104 @@ class Solution {
154
151
}
155
152
```
156
153
157
- ### ** Go**
158
-
159
- ``` go
160
- const mod int = 1e9 + 7
161
-
162
- func countPairs (deliciousness []int ) int {
163
- limit := 0
164
- for _ , d := range deliciousness {
165
- limit = max (limit, d)
166
- }
167
- limit *= 2
168
- pairs := 0
169
- freq := make (map [int ]int )
170
- for _ , d := range deliciousness {
171
- for sum := 1 ; sum <= limit; sum <<= 1 {
172
- pairs = (pairs + freq[sum-d]) % mod
173
- }
174
- freq[d]++
175
- }
176
- return pairs
177
- }
154
+ ### ** C++**
178
155
179
- func max (x , y int ) int {
180
- if x > y {
181
- return x
182
- }
183
- return y
184
- }
185
- ```
156
+ ``` cpp
157
+ class Solution {
158
+ public:
159
+ const int mod = 1e9 + 7;
186
160
187
- ``` go
188
- func countPairs (deliciousness []int ) int {
189
- cnt := map [int ]int {}
190
- for _ , v := range deliciousness {
191
- cnt[v]++
192
- }
193
- ans := 0
194
- mod := int (1e9 ) + 7
195
- for i := 0 ; i < 22 ; i++ {
196
- s := 1 << i
197
- for a , m := range cnt {
198
- b := s - a
199
- if n , ok := cnt[b]; ok {
200
- if a == b {
201
- ans += m * (m - 1 )
202
- } else {
203
- ans += m * n
204
- }
205
- }
206
- }
207
- }
208
- ans >>= 1
209
- return ans % mod
210
- }
161
+ int countPairs(vector<int>& deliciousness) {
162
+ int mx = *max_element(deliciousness.begin(), deliciousness.end()) << 1;
163
+ unordered_map<int, int> cnt;
164
+ int ans = 0;
165
+ for (auto& d : deliciousness) {
166
+ for (int s = 1; s <= mx; s <<= 1) {
167
+ ans = (ans + cnt[s - d]) % mod;
168
+ }
169
+ ++cnt[d];
170
+ }
171
+ return ans;
172
+ }
173
+ };
211
174
```
212
175
213
- ### ** C++**
214
-
215
176
``` cpp
216
177
class Solution {
217
178
public:
179
+ const int mod = 1e9 + 7;
180
+
218
181
int countPairs(vector<int>& deliciousness) {
219
182
unordered_map<int, int> cnt;
220
- for (int v : deliciousness) ++cnt[ v ] ;
183
+ for (int& d : deliciousness) ++cnt[d ];
221
184
long long ans = 0;
222
185
for (int i = 0; i < 22; ++i) {
223
186
int s = 1 << i;
224
187
for (auto& [a, m] : cnt) {
225
188
int b = s - a;
226
189
if (!cnt.count(b)) continue;
227
- if (a == b) ans += 1ll * m * (m - 1);
228
- else ans += 1ll * m * cnt[ b] ;
190
+ ans += 1ll * m * (a == b ? (m - 1) : cnt[b]);
229
191
}
230
192
}
231
193
ans >>= 1 ;
232
- int mod = 1e9 + 7;
233
- return (int) (ans % mod);
194
+ return ans % mod;
234
195
}
235
196
};
236
197
```
237
198
199
+ ### ** Go**
200
+
201
+ ``` go
202
+ func countPairs (deliciousness []int ) (ans int ) {
203
+ mx := 0
204
+ for _ , d := range deliciousness {
205
+ mx = max (mx, d)
206
+ }
207
+ mx <<= 1
208
+ const mod int = 1e9 + 7
209
+ cnt := map [int ]int {}
210
+ for _ , d := range deliciousness {
211
+ for s := 1 ; s <= mx; s <<= 1 {
212
+ ans = (ans + cnt[s-d]) % mod
213
+ }
214
+ cnt[d]++
215
+ }
216
+ return
217
+ }
218
+
219
+ func max (a , b int ) int {
220
+ if a > b {
221
+ return a
222
+ }
223
+ return b
224
+ }
225
+ ```
226
+
227
+ ``` go
228
+ func countPairs (deliciousness []int ) (ans int ) {
229
+ cnt := map [int ]int {}
230
+ for _ , d := range deliciousness {
231
+ cnt[d]++
232
+ }
233
+ const mod int = 1e9 + 7
234
+ for i := 0 ; i < 22 ; i++ {
235
+ s := 1 << i
236
+ for a , m := range cnt {
237
+ b := s - a
238
+ if n , ok := cnt[b]; ok {
239
+ if a == b {
240
+ ans += m * (m - 1 )
241
+ } else {
242
+ ans += m * n
243
+ }
244
+ }
245
+ }
246
+ }
247
+ ans >>= 1
248
+ return ans % mod
249
+ }
250
+ ```
251
+
238
252
### ** ...**
239
253
240
254
```
0 commit comments