遍历。
给你一个 正整数数组 nums 。
你需要检查是否可以从数组中选出两个或更多元素,满足这些元素的按位或运算( OR)结果的二进制表示中至少存在一个尾随零(最低位为 0)。
或运算要求两个元素的最低位都为 0,才能使得结果的最低位为 0,即至少存在一个尾随零。
于是问题转换为正整数数组 nums 至少存在 2 个最低位为 0 的元素,即至少存在 2 个偶数。
/*
* @lc app=leetcode.cn id=2980 lang=cpp
*
* [2980] 检查按位或是否存在尾随零
*/
// @lc code=start
class Solution
{
public:
bool hasTrailingZeros(vector<int> &nums)
{
int count = 0;
for (int &num : nums)
if (num % 2 == 0)
count++;
return count >= 2;
}
};
// @lc code=end
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(1)。
滑动窗口枚举窗口内字符相同的字符串,再暴力枚举长度相等的字符串。
/*
* @lc app=leetcode.cn id=2981 lang=cpp
*
* [2981] 找出出现至少三次的最长特殊子字符串 I
*/
// @lc code=start
class Solution
{
public:
int maximumLength(string s)
{
// 特判
if (s.empty())
return 0;
int n = s.size();
int ans = -1, left = 0;
for (int right = 0; right < n; right++)
{
while (s[left] != s[right])
left++;
int len = right - left + 1;
string sub = s.substr(left, len);
int count = 1;
// 暴力枚举所有的子字符串
for (int i = left + 1; i < n; i++)
{
string temp = s.substr(i, len);
if (sub == temp)
{
count++;
if (count >= 3)
{
ans = max(ans, len);
break;
}
}
}
}
return ans;
}
};
// @lc code=end
时间复杂度:O(n2),其中 n 是字符串 s 的长度。
空间复杂度:O(1)。现至少三次的最长特殊子字符串 II
字符串分割 + 分类讨论。
按照相同字母分组,每组统计相同字母连续出现的长度。例如 aaaabbbabb 把 a 分成一组,组内有长度 4 和长度 1;把 b 分成一组,组内有长度 3 和长度 2。
单独考虑每一组,按照长度从大到小排序,设长度列表为 group。
分类讨论:
这三种情况取最大值,即:max({group[0] - 2, min(group[0] - 1, group[1]), group[2]})。取每一组的最大值,即为答案。
如果答案是 0,返回 −1。
代码实现时,无需特判 group 数组长度小于 3 的情况,我们只需要在数组添加两个空串(在数组末尾加两个 0)即可。
/*
* @lc app=leetcode.cn id=2981 lang=cpp
*
* [2981] 找出出现至少三次的最长特殊子字符串 I
*/
// @lc code=start
class Solution
{
public:
int maximumLength(string s)
{
// 特判
if (s.empty())
return 0;
vector<int> groups[26];
int n = s.length();
int count = 0;
for (int i = 0; i < n; i++)
{
count++;
if (i + 1 == n || s[i] != s[i + 1])
{
groups[s[i] - 'a'].push_back(count); // 统计连续字符长度
count = 0;
}
}
int ans = 0;
for (vector<int> &group : groups)
{
if (group.empty())
continue;
// 降序排序
sort(group.begin(), group.end(), greater<int>());
// 假设还有两个空串
group.push_back(0);
group.push_back(0);
ans = max({ans, group[0] - 2, min(group[0] - 1, group[1]), group[2]});
}
return ans == 0 ? -1 : ans;
}
};
// @lc code=end
时间复杂度:O(nlogn),其中 n 是字符串 s 的长度。
空间复杂度:O(n),其中 n 是字符串 s 的长度。
大模拟。
题解:分类讨论(Python/Java/C++/Go)
/*
* @lc app=leetcode.cn id=2983 lang=cpp
*
* [2983] 回文串重新排列查询
*/
// @lc code=start
class Solution
{
public:
vector<bool> canMakePalindromeQueries(string s, vector<vector<int>> &queries)
{
// 分成左右两半,右半反转
int n = s.length() / 2;
string t = s.substr(n);
reverse(t.begin(), t.end());
// 预处理三种前缀和
vector<vector<int>> sum_s(n + 1, vector<int>(26));
for (int i = 0; i < n; i++)
{
sum_s[i + 1] = sum_s[i];
sum_s[i + 1][s[i] - 'a']++;
}
vector<vector<int>> sum_t(n + 1, vector<int>(26));
for (int i = 0; i < n; i++)
{
sum_t[i + 1] = sum_t[i];
sum_t[i + 1][t[i] - 'a']++;
}
vector<int> sum_ne(n + 1);
for (int i = 0; i < n; i++)
{
sum_ne[i + 1] = sum_ne[i] + (s[i] != t[i]);
}
// 计算子串中各个字符的出现次数,闭区间 [l, r]
auto count = [](vector<vector<int>> &sum, int l, int r) -> vector<int>
{
auto res = sum[r + 1];
for (int i = 0; i < 26; i++)
{
res[i] -= sum[l][i];
}
return res;
};
auto subtract = [](vector<int> s1, vector<int> s2) -> vector<int>
{
for (int i = 0; i < 26; i++)
{
s1[i] -= s2[i];
if (s1[i] < 0)
{
return {};
}
}
return s1;
};
auto check = [&](int l1, int r1, int l2, int r2, vector<vector<int>> &sumS, vector<vector<int>> &sumT) -> bool
{
if (sum_ne[l1] > 0 || // [0, l1-1] 有 s[i] != t[i]
sum_ne[n] - sum_ne[max(r1, r2) + 1] > 0)
{ // [max(r1,r2)+1, n-1] 有 s[i] != t[i]
return false;
}
// 区间包含
if (r2 <= r1)
{
return count(sumS, l1, r1) == count(sumT, l1, r1);
}
// 区间不相交
if (r1 < l2)
{
return sum_ne[l2] - sum_ne[r1 + 1] == 0 && // [r1+1, l2-1] 都满足 s[i] == t[i]
count(sumS, l1, r1) == count(sumT, l1, r1) &&
count(sumS, l2, r2) == count(sumT, l2, r2);
}
// 区间相交但不包含
auto s1 = subtract(count(sumS, l1, r1), count(sumT, l1, l2 - 1));
auto s2 = subtract(count(sumT, l2, r2), count(sumS, r1 + 1, r2));
return !s1.empty() && !s2.empty() && s1 == s2;
};
vector<bool> ans(queries.size());
for (int i = 0; i < queries.size(); i++)
{
auto &q = queries[i];
int l1 = q[0], r1 = q[1], l2 = n * 2 - 1 - q[3], r2 = n * 2 - 1 - q[2];
ans[i] = l1 <= l2 ? check(l1, r1, l2, r2, sum_s, sum_t) : check(l2, r2, l1, r1, sum_t, sum_s);
}
return ans;
}
};
// @lc code=end
时间复杂度:O((n+q)∣Σ∣),其中 n 为字符串 s 的长度,q 为数组 queries 的长度,∣Σ∣ 为字符集合的大小,本题中字符均为小写字母,所以 ∣Σ∣=26。回答每个询问的时间是 O(∣Σ∣)。
空间复杂度:O(n∣Σ∣),其中 n 为字符串 s 的长度,∣Σ∣ 为字符集合的大小,本题中字符均为小写字母,所以 ∣Σ∣=26。