(感觉 LeetCode 上的题不需要考虑复杂度,能想出来做法就能过
题目:给你两个只包含 ‘x’, ‘y’ 的字符串 s 1 , s 2 s1, s2 s1,s2 ,每次操作可以交换两个分别位于两个字符串中的字符,问最少交换几次可以使字符串变为完全相同。
分析:首先两个字符串 ‘x’,‘y’ 总数不是偶数,都是不行的。
只关心字符串不相同的位置,(x -> y) 或者 (y -> x)。统计两者个数 a n s 1 , a n s 2 ans1, ans2 ans1,ans2。两个 (x -> y) 可以用一次操作消除,(y -> x)同理。
class Solution {
public:
int minimumSwap(string s1, string s2) {
map<char, int> mp;
int s1Size = s1.size();
int ans1 = 0, ans2 = 0;
for (int i = 0; i < s1Size; i++) {
if (s1[i] != s2[i]) {
if (s1[i] == 'x') ans1++;
else ans2++;
}
mp[s1[i]]++; mp[s2[i]]++;
}
if ((mp['x'] & 1) || (mp['y'] & 1)) return -1;
return ans1 / 2 + ans2 / 2 + (ans1 % 2 + ans2 % 2);
}
};
题目:给一个数组 n u m s nums nums 和 k k k。问奇数个数为 k k k 的子数组有多少。
分析:考虑找到了一个元区间 ( i , j ) (i, j) (i,j),刚好奇数个数为 k k k,且端点都是奇数。统计两端各有多少 0,(分别用 x, y 表示)。那么对于这个区间能构成的子数组数量为 a n s = x ∗ y + x + y + 1 ans = x * y + x + y + 1 ans=x∗y+x+y+1
2 2 2 1 2 1 2 2 2
2
对于 1 2 1 元区间, x = 3 , y = 3 x = 3, y = 3 x=3,y=3,则 a n s = 3 ∗ 3 + 3 + 3 + 1 = 16 ans = 3 * 3 + 3 + 3 + 1 = 16 ans=3∗3+3+3+1=16。
遍历所有元区间即可加和即可。
class Solution {
public:
int numberOfSubarrays(vector<int>& nums, int k) {
int ans = 0, n = nums.size();
int pos[50010], cnt = 0;
for (int i = 0; i < n; i++) { // 记录奇数位置的下标
if (nums[i] & 1) pos[cnt++] = i;
}
if (cnt < k) return 0;
int i = 0, j = k - 1;
int L = -1; pos[cnt] = n; // 加上边界
while (j < cnt) {
int x = pos[i] - L - 1;
int y = pos[j + 1] - pos[j] - 1;
L = pos[i];
i++; j++;
ans += (x * y + x + y + 1);
}
return ans;
}
};
大神做法:
首先 e q u a l r a n g e ( ) equalrange() equalrange() 是 S T L STL STL 中的函数,返回一个区间的左右端点,分别代表 l o w e r b o u n d , u p p e r b o u n d lowerbound, upperbound lowerbound,upperbound。
预处理奇数数量的前缀和。之后对于每一位直接求满足条件的区间长度即可。
class Solution {
public:
int numberOfSubarrays(vector<int>& a, int k) {
int n = a.size();
vector<int> s(n+1);
for (int i = 1; i <= n; ++ i)
s[i] = s[i-1]+a[i-1]%2;
int ret = 0;
for (int i = 0; i < n; ++ i)
{
auto p = equal_range(s.begin(), s.end(), s[i]+k);
ret += p.second-p.first;
}
return ret;
}
};
题目:给字符串 s(由括号,小写字母组成),返回有效字符串(括号相对应)。
分析:用栈匹配括号,删去无效括号即可。
class Solution {
public:
string minRemoveToMakeValid(string s) {
stack<int> st; string ans;
vector<int> pos(s.size(), 1);
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') st.push(i);
else if (s[i] == ')') {
if (st.empty()) pos[i]--;
else st.pop();
}
}
while (!st.empty()) {
pos[st.top()]--; st.pop();
}
for (int i = 0; i < s.size(); i++) if (pos[i]) ans += s[i];
return ans;
}
};
题目:
分析:裴蜀定理:
要使 a 1 ∗ x 1 + a 2 ∗ x 2 + … + a n ∗ x n = k a_{1} * x_{1}+a_{2} * x_{2}+\ldots+a_{n} * x_{n}=k a1∗x1+a2∗x2+…+an∗xn=k 有解, g c d ( a 1 + a 2 + … + a n ) ∣ k g c d\left(a_{1}+a_{2}+\ldots+a_{n}\right) | k gcd(a1+a2+…+an)∣k
求所有数最大公约数是否等于 1 即可。
class Solution {
public:
bool isGoodArray(vector<int>& a) {
int n = a.size();
int ret = a[0];
for (auto x : a) ret = __gcd(ret, x);
return ret == 1;
}
};