1. 可以读通讯稿的组数
经典的哈希做法代替双指针的题。我们可以将原式进行移项,将自身与自身的镜像值相减(这里的差值我们记作dist)。
那么问题就变成了:自身与自身的镜像值相减 相等的对数,那么很显然就是
C
n
2
=
n
∗
(
n
−
1
)
2
C_n^2 = \frac{ n * (n-1) } {2}
Cn2=2n∗(n−1)
所以我们只需要去使用哈希表记录dist 的个数,最后使用组合数计算一下即可。
class Solution {
public:
using ll = long long;
static const int mod = 1e9+7;
int numberOfPairs(vector<int>& nums) {
unordered_map<ll, ll> mp;
ll ans = 0;
for(auto c : nums){
string r = to_string(c);
reverse(r.begin(), r.end());
int cur = c, rev = stoi(r);
mp[cur-rev] += 1;
}
for(auto &[k, v] : mp){
ans += 1LL * v * (v-1) / 2;
}
return ans % mod;
}
};
2. 池塘计数
这一题呢就是一个经典的搜索加标记了:没遇见一块积水,则以改位置展开搜索,标记所有与其相连的积水即可。
class Solution {
public:
int lakeCount(vector<string>& field) {
const int N = 110;
const int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dy[] = {1, 0, -1, 1, -1, 1, 0, -1};
int vis[N][N], ans = 0;
memset(vis, 0, sizeof(vis));
int n = field.size(), m = field[0].size();
function<void(int, int)> dfs = [&](int x, int y) -> void {
for(int i = 0; i < 8; i++){
int nx = x + dx[i], ny = y + dy[i];
if(nx < 0 || nx >= n || ny < 0 || ny >= m || vis[nx][ny] || field[nx][ny] == '.') continue;
vis[nx][ny] = 1;
dfs(nx, ny);
}
};
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(field[i][j] == 'W' && vis[i][j] == 0){
dfs(i, j);
ans += 1;
}
}
}
return ans;
}
};
3. 数字默契考验
容易发现,若有解,即最小相等的数字则为所有数的 LCM (最小公倍数),所以我们可以先求出LCM,然后判断每个数(记为C)增大的倍数dist = LCM / C,如果dist 可以被分解为 P个2与Q个3的乘积, 即:
d
i
s
t
=
2
P
∗
3
Q
(
P
,
Q
≥
0
)
dist = 2 ^ P * 3 ^ Q (P, Q \ge 0)
dist=2P∗3Q(P,Q≥0),则说明该数可以通过乘 2 何乘 3 增大 直至等于 LCM,否则说明存在一个数不满足条件,则返回 -1,表示无解。
tips: 求解LCM 和 dist 的时候记得都开long long 否则 可能溢出,导致结果不正确
class Solution {
public:
using ll = long long;
int minOperations(vector<int>& numbers) {
ll n = numbers.size(), ans = 0, lcm = 1;
for(auto &c : numbers) lcm = ::std::lcm(lcm, 1LL * c);
for(auto c : numbers) {
ll dist = lcm / c, cnt = 0;
while(dist % 2 == 0){
dist /= 2;
cnt++;
}
while(dist % 3 == 0){
dist /= 3;
cnt++;
}
if(dist == 1) ans += cnt;
else return -1;
}
return ans;
}
};