第一题
题目链接
题解
用set比较即可。
class Solution {
public:
int similarPairs(vector<string>& words) {
vector<set<char>> a(words.size());
int ans = 0;
for (int i = 0; i < words.size(); i++) {
set<char> b(begin(words[i]),end(words[i]));
a[i] = b;
for (int j = 0; j < i; j++) {
if (a[j] == b) ans++;
}
}
return ans;
}
};
复杂度分析
时间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n为words的长度。
第二题
题目链接
题解
不断循环,找出全部质因数求和,直到质因数和与原数相同,即为所求最小值。
class Solution {
public:
int find(int n) {
int ans = 0;
int t = n;
for (int i = 2; i <= n; i++) {
while(t % i == 0) {
t /= i;
ans += i;
}
if (t == 1) break;
}
return ans;
}
int smallestValue(int n) {
int ans = n;
while(1) {
ans = find(n);
if (ans == n) break;
n = ans;
}
return ans;
}
};
复杂度分析
时间复杂度为 O ( n ) O(\sqrt{n}) O(n)。
第三题
题目链接
题解
这道题分析清楚情况很简单。
我是用map存储了两个顶点是否存在,当然也可以用set存储某条边是否存在。
根据所有节点度数之和必为偶数,我们可以得知必不存在奇数个度数为奇数的节点。
根据最多添加两条边,且无自环重边的要求,我们可知:
- 当度数为奇数的节点(下简称奇节点)个数大于4时,无论如何都无法找到两条边使所有节点度数为偶数。
- 当奇节点个数为0时,我们直接返回true。
- 那么我们只需要讨论奇节点个数为2和为4的情况。
- 当奇节点个数为2时,如果存在一个节点度数为0,或存在一个节点与这两个奇节点之间都没有边,或两个节点之间没有边,则返回true;否则返回false。
- 当奇节点个数为4时,我们只需判断这四个节点能否分成两组,每组中的两个点之间都不存在边。如果可以就返回true,否则返回false。
class Solution {
public:
bool isPossible(int n, vector<vector<int>>& edges) {
map<int,map<int,int>> a;
map<int,vector<int>> m;
for (int i = 0; i < edges.size(); i++) {
m[edges[i][0]].push_back(edges[i][1]);
m[edges[i][1]].push_back(edges[i][0]);
a[edges[i][0]][edges[i][1]] = 1;
a[edges[i][1]][edges[i][0]] = 1;
if (m[edges[i][0]].size() == n - 1 && n % 2 == 0) return false;
if (m[edges[i][1]].size() == n - 1 && n % 2 == 0) return false;
}
map<int,vector<int>> d;
for (int i = 1; i <= n; i++) {
if (m.count(i)) {
d[m[i].size()%2 + 1].push_back(i);
} else {
d[0].push_back(i);
}
}
if (d.count(2)&&d[2].size()>4) return false;
if (d.count(2) == 0) return true;
if (d[2].size() == 2) {
if (d.count(0)) return true;
if (a[d[2][0]][d[2][1]] == 0) return true;
for (int i = 0; i < d[1].size(); i++) {
if (a[d[2][0]][d[1][i]] == 0 && a[d[2][1]][d[1][i]] == 0) return true;
}
} else if (d[2].size() == 4) {
if (a[d[2][0]][d[2][1]]==0 && a[d[2][2]][d[2][3]]==0) return true;
if (a[d[2][0]][d[2][2]]==0 && a[d[2][1]][d[2][3]]==0) return true;
if (a[d[2][0]][d[2][3]]==0 && a[d[2][1]][d[2][2]]==0) return true;
}
return false;
}
};
复杂度分析
时间复杂度为 O ( m + n ) O(m+n) O(m+n),其中m为edges的长度。
第四题
题目链接
题解
这道题可以先分别计算两个点到根节点的距离,求和得到a,然后求出两个点最近的父节点到根节点的距离b,易证题目所求即为a-2*b+1。
class Solution {
public:
int find(long long n) {
int ans = 0;
while(n != 1) {
n /= 2;
ans++;
}
return ans;
}
vector<int> cycleLengthQueries(int n, vector<vector<int>>& q) {
vector<int> ans(q.size());
for (int i = 0; i < q.size(); i++) {
int left = find(q[i][0]);
int right = find(q[i][1]);
int flag = 1;
while(q[i][0] != 1 && q[i][1] != 1) {
if (q[i][0] > q[i][1]) q[i][0] /= 2;
else if (q[i][1] > q[i][0]) q[i][1] /= 2;
else {
flag = q[i][1];
break;
}
}
if (flag == 1) ans[i] = left + right + 1;
else {
int d = find(flag);
ans[i] = left + right + 1 - 2 * d;
}
}
return ans;
}
};
复杂度分析
时间复杂度为 O ( n m ) O(nm) O(nm),其中m为q的长度。