目录
3001. 捕获黑皇后需要的最少移动次数
现有一个下标从 1 开始的 8 x 8
棋盘,上面有 3
枚棋子。
给你 6
个整数 a
、b
、c
、d
、e
和 f
,其中:
(a, b)
表示白色车的位置。(c, d)
表示白色象的位置。(e, f)
表示黑皇后的位置。
假定你只能移动白色棋子,返回捕获黑皇后所需的最少移动次数。
请注意:
- 车可以向垂直或水平方向移动任意数量的格子,但不能跳过其他棋子。
- 象可以沿对角线方向移动任意数量的格子,但不能跳过其他棋子。
- 如果车或象能移向皇后所在的格子,则认为它们可以捕获皇后。
- 皇后不能移动。
示例 1:
输入:a = 1, b = 1, c = 8, d = 8, e = 2, f = 3 输出:2 解释:将白色车先移动到 (1, 3) ,然后移动到 (2, 3) 来捕获黑皇后,共需移动 2 次。 由于起始时没有任何棋子正在攻击黑皇后,要想捕获黑皇后,移动次数不可能少于 2 次。
示例 2:
输入:a = 5, b = 3, c = 3, d = 4, e = 5, f = 2 输出:1 解释:可以通过以下任一方式移动 1 次捕获黑皇后: - 将白色车移动到 (5, 2) 。 - 将白色象移动到 (5, 2) 。
提示:
1 <= a, b, c, d, e, f <= 8
- 两枚棋子不会同时出现在同一个格子上。
class Solution {
public:
int minMovesToCaptureTheQueen(int a, int b, int c, int d, int e, int f) {
Point p1(a, b), p2(c, d), p3(e, f);
if ((a == e || b == f)&&(!IsPointInLine(Line(p1,p3),p2)||!PointInSegment(p1,p3,p2))) return 1;
if ((c + d == e + f || c - d == e - f)&&(!IsPointInLine(Line(p2, p3), p1)|| !PointInSegment(p2, p3, p1)))return 1;
return 2;
}
};
3002. 移除后集合的最多元素数
给你两个下标从 0
开始的整数数组 nums1
和 nums2
,它们的长度都是偶数 n
。
你必须从 nums1
中移除 n / 2
个元素,同时从 nums2
中也移除 n / 2
个元素。移除之后,你将 nums1
和 nums2
中剩下的元素插入到集合 s
中。
返回集合 s
可能的 最多 包含多少元素。
示例 1:
输入:nums1 = [1,2,1,2], nums2 = [1,1,1,1] 输出:2 解释:从 nums1 和 nums2 中移除两个 1 。移除后,数组变为 nums1 = [2,2] 和 nums2 = [1,1] 。因此,s = {1,2} 。 可以证明,在移除之后,集合 s 最多可以包含 2 个元素。
示例 2:
输入:nums1 = [1,2,3,4,5,6], nums2 = [2,3,2,3,2,3] 输出:5 解释:从 nums1 中移除 2、3 和 6 ,同时从 nums2 中移除两个 3 和一个 2 。移除后,数组变为 nums1 = [1,4,5] 和 nums2 = [2,3,2] 。因此,s = {1,2,3,4,5} 。 可以证明,在移除之后,集合 s 最多可以包含 5 个元素。
示例 3:
输入:nums1 = [1,1,2,2,3,3], nums2 = [4,4,5,5,6,6] 输出:6 解释:从 nums1 中移除 1、2 和 3 ,同时从 nums2 中移除 4、5 和 6 。移除后,数组变为 nums1 = [1,2,3] 和 nums2 = [4,5,6] 。因此,s = {1,2,3,4,5,6} 。 可以证明,在移除之后,集合 s 最多可以包含 6 个元素。
提示:
n == nums1.length == nums2.length
1 <= n <= 2 * 104
n
是偶数。1 <= nums1[i], nums2[i] <= 109
class Solution {
public:
int maximumSetSize(vector<int>& nums1, vector<int>& nums2) {
set<int>s1, s2, s3;
int s = 0;
for (auto x : nums1)s1.insert(x);
for (auto x : nums2) {
s2.insert(x);
if (s1.find(x) != s1.end())s3.insert(x);
}
int a = s3.size(), n = nums1.size() / 2;
int b = s1.size() - a, c = s2.size() - a;
return min(min(b, n) + min(c, n) + a, n + n);
}
};
3005. 最大频率元素计数
给你一个由 正整数 组成的数组 nums
。
返回数组 nums
中所有具有 最大 频率的元素的 总频率 。
元素的 频率 是指该元素在数组中出现的次数。
示例 1:
输入:nums = [1,2,2,3,1,4] 输出:4 解释:元素 1 和 2 的频率为 2 ,是数组中的最大频率。 因此具有最大频率的元素在数组中的数量是 4 。
示例 2:
输入:nums = [1,2,3,4,5] 输出:5 解释:数组中的所有元素的频率都为 1 ,是最大频率。 因此具有最大频率的元素在数组中的数量是 5 。
提示:
1 <= nums.length <= 100
1 <= nums[i] <= 100
class Solution {
public:
int maxFrequencyElements(vector<int>& nums) {
map<int, int>m;
int s = 0, num = 0;
for (auto x : nums)s = max(s, ++m[x]);
for (auto mi : m)if (mi.second == s)num++;
return num * s;
}
};
3011. 判断一个数组是否可以变为有序
3018. 可处理的最大删除操作数 I
3019. 按键变更的次数
给你一个下标从 0 开始的字符串 s
,该字符串由用户输入。按键变更的定义是:使用与上次使用的按键不同的键。例如 s = "ab"
表示按键变更一次,而 s = "bBBb"
不存在按键变更。
返回用户输入过程中按键变更的次数。
注意:shift
或 caps lock
等修饰键不计入按键变更,也就是说,如果用户先输入字母 'a'
然后输入字母 'A'
,不算作按键变更。
示例 1:
输入:s = "aAbBcC" 输出:2 解释: 从 s[0] = 'a' 到 s[1] = 'A',不存在按键变更,因为不计入 caps lock 或 shift 。 从 s[1] = 'A' 到 s[2] = 'b',按键变更。 从 s[2] = 'b' 到 s[3] = 'B',不存在按键变更,因为不计入 caps lock 或 shift 。 从 s[3] = 'B' 到 s[4] = 'c',按键变更。 从 s[4] = 'c' 到 s[5] = 'C',不存在按键变更,因为不计入 caps lock 或 shift 。
示例 2:
输入:s = "AaAaAaaA" 输出:0 解释: 不存在按键变更,因为这个过程中只按下字母 'a' 和 'A' ,不需要进行按键变更。
提示:
1 <= s.length <= 100
s
仅由英文大写字母和小写字母组成。
class Solution {
public:
int countKeyChanges(string s) {
s[0] = tolower(s[0]);
int ans = 0;
for (int i = 1; i < s.length(); i++) {
s[i] = tolower(s[i]);
if (s[i] != s[i - 1])ans++;
}
return ans;
}
};
3023. 在无限流中寻找模式 I
3032. 统计各位数字都不同的数字个数 II
给你两个 正整数 a
和 b
,返回 闭区间 [a, b]
内各位数字都不同的数字个数。
示例 1:
输入:a = 1, b = 20 输出:19 解释:除 11 以外,区间 [1, 20] 内的所有数字的各位数字都不同。因此,答案为 19 。
示例 2:
输入:a = 9, b = 19 输出:10 解释:除 11 以外,区间 [1, 20] 内的所有数字的各位数字都不同。因此,答案为 10 。
示例 3:
输入:a = 80, b = 120 输出:27 解释:区间 [80, 120] 内共有 41 个整数,其中 27 个数字的各位数字都不同。
提示:
1 <= a <= b <= 1000
class Solution {
public:
int numberCount(int a, int b) {
int n = 0;
for (int i = a; i <= b; i++)if (check(i))n++;
return n;
}
bool check(int x) {
set<int>s;
int n = 0;
while (x)s.insert(x % 10), x /= 10, n++;
return n == s.size();
}
};
3037. 在无限流中寻找模式 II
3038. 相同分数的最大操作数目 I
给你一个整数数组 nums
,如果 nums
至少 包含 2
个元素,你可以执行以下操作:
- 选择
nums
中的前两个元素并将它们删除。
一次操作的 分数 是被删除元素的和。
在确保 所有操作分数相同 的前提下,请你求出 最多 能进行多少次操作。
请你返回按照上述要求 最多 可以进行的操作次数。
示例 1:
输入:nums = [3,2,1,4,5] 输出:2 解释:我们执行以下操作: - 删除前两个元素,分数为 3 + 2 = 5 ,nums = [1,4,5] 。 - 删除前两个元素,分数为 1 + 4 = 5 ,nums = [5] 。 由于只剩下 1 个元素,我们无法继续进行任何操作。
示例 2:
输入:nums = [3,2,6,1,4] 输出:1 解释:我们执行以下操作: - 删除前两个元素,分数为 3 + 2 = 5 ,nums = [6,1,4] 。 由于下一次操作的分数与前一次不相等,我们无法继续进行任何操作。
提示:
2 <= nums.length <= 100
1 <= nums[i] <= 1000
class Solution {
public:
int maxOperations(vector<int>& nums) {
int ans=1,s=nums[0]+nums[1];
for(int i=3;i<nums.size();i+=2){
if(nums[i]+nums[i-1]-s)break;
ans++;
}
return ans;
}
};
3040. 相同分数的最大操作数目 II
给你一个整数数组 nums
,如果 nums
至少 包含 2
个元素,你可以执行以下操作中的 任意 一个:
- 选择
nums
中最前面两个元素并且删除它们。 - 选择
nums
中最后两个元素并且删除它们。 - 选择
nums
中第一个和最后一个元素并且删除它们。
一次操作的 分数 是被删除元素的和。
在确保 所有操作分数相同 的前提下,请你求出 最多 能进行多少次操作。
请你返回按照上述要求 最多 可以进行的操作次数。
示例 1:
输入:nums = [3,2,1,2,3,4] 输出:3 解释:我们执行以下操作: - 删除前两个元素,分数为 3 + 2 = 5 ,nums = [1,2,3,4] 。 - 删除第一个元素和最后一个元素,分数为 1 + 4 = 5 ,nums = [2,3] 。 - 删除第一个元素和最后一个元素,分数为 2 + 3 = 5 ,nums = [] 。 由于 nums 为空,我们无法继续进行任何操作。
示例 2:
输入:nums = [3,2,6,1,4] 输出:2 解释:我们执行以下操作: - 删除前两个元素,分数为 3 + 2 = 5 ,nums = [6,1,4] 。 - 删除最后两个元素,分数为 1 + 4 = 5 ,nums = [6] 。 至多进行 2 次操作。
提示:
2 <= nums.length <= 2000
1 <= nums[i] <= 1000
class Solution {
public:
int maxOperations(vector<int>& nums) {
int s1=nums[0]+nums[1],s2=nums[0]+nums[nums.size()-1],s3=nums[nums.size()-2]+nums[nums.size()-1];
int ans=maxOperations(nums,s1);
if(s2!=s1)ans=max(ans,maxOperations(nums,s2));
if(s3!=s1 && s3!=s2)ans=max(ans,maxOperations(nums,s3));
return ans;
}
int maxOperations(vector<int>& nums,int s) {
m.clear();
return maxOperations(nums,0,nums.size()-1,s);
}
int maxOperations(vector<int>& nums,int low,int high,int s) {
if(m[low].find(high)!=m[low].end())return m[low][high];
if(low>=high)return 0;
int ans=0;
if(nums[low]+nums[low+1]==s)ans=maxOperations(nums,low+2,high,s)+1;
if(nums[high]+nums[high-1]==s)ans=max(ans,maxOperations(nums,low,high-2,s)+1);
if(nums[low]+nums[high]==s)ans=max(ans,maxOperations(nums,low+1,high-1,s)+1);
return m[low][high]=ans;
}
unordered_map<int,unordered_map<int,int>>m;
};
3046. 分割数组
给你一个长度为 偶数 的整数数组 nums
。你需要将这个数组分割成 nums1
和 nums2
两部分,要求:
nums1.length == nums2.length == nums.length / 2
。nums1
应包含 互不相同 的元素。nums2
也应包含 互不相同 的元素。
如果能够分割数组就返回 true
,否则返回 false
。
示例 1:
输入:nums = [1,1,2,2,3,4] 输出:true 解释:分割 nums 的可行方案之一是 nums1 = [1,2,3] 和 nums2 = [1,2,4] 。
示例 2:
输入:nums = [1,1,1,1] 输出:false 解释:分割 nums 的唯一可行方案是 nums1 = [1,1] 和 nums2 = [1,1] 。但 nums1 和 nums2 都不是由互不相同的元素构成。因此,返回 false 。
提示:
1 <= nums.length <= 100
nums.length % 2 == 0
1 <= nums[i] <= 100
class Solution {
public:
bool isPossibleToSplit(vector<int>& nums) {
sort(nums.begin(), nums.end());
for (int i = 2; i < nums.size(); i++) {
if (nums[i] == nums[i - 2])return false;
}
return true;
}
};
3062. 链表游戏的获胜者
给定长度为 偶数 ,包含整数的链表的 head
节点。
每个 奇数编号 的节点包含一个奇数,并且每个 偶数编号 的节点包含一个偶数。
我们把每个偶数编号的节点和它的下一个节点叫做一个 对,例如编号为 0
和 1
的节点是一对,编号为 2 和 3 的节点是一对,以此类推。
对于每个 对,我们比较对中节点的值:
- 如果奇数节点更大,
"Odd"
队得一分。 - 如果偶数节点更大,"Even" 队得一分。
返回分数更 高 的队名,如果分数相同,返回 "Tie"
。
示例 1:
输入:head = [2,1] 输出:"Even" 解释:链表中只有一个对 (2,1)。因为 2 > 1,偶数队得分。 因此,答案是 "Even"。
示例 2:
输入:head = [2,5,4,7,20,5] 输出:"Odd" 解释:此链表中有 3 对。让我们分别对每一对进行分析: (2,5) -> 因为 2 < 5,奇数队得分。 (4,7) -> 因为 4 < 7,奇数队得分。 (20,5) -> 因为 20 > 5,偶数队得分。 奇数队得 2 分,偶数队得 1 分,奇数队得分更高。 因此,答案是 "Odd"。
示例 3:
输入:head = [4,5,2,1] 输出:"Tie" 解释:此链表中有 2 对。让我们分别对每一对进行分析: (4,5) -> 因为 4 < 5,奇数队得分。 (2,1) -> 因为 2 > 1,偶数队得分。 每队得 1 分。 因此,答案是 "Tie"。
提示:
- 链表中节点的数字在范围
[2, 100]
内。 - 链表中的节点数为偶数。
1 <= Node.val <= 100
- 每个奇数编号节点的值都是奇数。
- 每个偶数编号节点的值都是偶数。
class Solution {
public:
string gameResult(ListNode* head) {
int s=0;
while(head){
int a=head->val;
head=head->next;
a-=head->val;
head=head->next;
if(a>0)s++;
else s--;
}
if(s>0)return "Even";
if(s<0)return "Odd";
return "Tie";
}
};
3063. 链表频率
3064. 使用按位查询猜测数字 I
3065. 超过阈值的最少操作数 I
给你一个下标从 0 开始的整数数组 nums
和一个整数 k
。
一次操作中,你可以删除 nums
中的最小元素。
你需要使数组中的所有元素都大于或等于 k
,请你返回需要的 最少 操作次数。
示例 1:
输入:nums = [2,11,10,1,3], k = 10 输出:3 解释:第一次操作后,nums 变为 [2, 11, 10, 3] 。 第二次操作后,nums 变为 [11, 10, 3] 。 第三次操作后,nums 变为 [11, 10] 。 此时,数组中的所有元素都大于等于 10 ,所以我们停止操作。 使数组中所有元素都大于等于 10 需要的最少操作次数为 3 。
示例 2:
输入:nums = [1,1,2,4,9], k = 1 输出:0 解释:数组中的所有元素都大于等于 1 ,所以不需要对 nums 做任何操作。
示例 3:
输入:nums = [1,1,2,4,9], k = 9 输出:4 解释:nums 中只有一个元素大于等于 9 ,所以需要执行 4 次操作。
提示:
1 <= nums.length <= 50
1 <= nums[i] <= 109
1 <= k <= 109
- 输入保证至少有一个满足
nums[i] >= k
的下标i
存在。
class Solution {
public:
int minOperations(vector<int>& nums, int k) {
int s=0;
for(auto x:nums)s+=(x<k);
return s;
}
};
3066. 超过阈值的最少操作数 II
给你一个下标从 0 开始的整数数组 nums
和一个整数 k
。
一次操作中,你将执行:
- 选择
nums
中最小的两个整数x
和y
。 - 将
x
和y
从nums
中删除。 - 将
min(x, y) * 2 + max(x, y)
添加到数组中的任意位置。
注意,只有当 nums
至少包含两个元素时,你才可以执行以上操作。
你需要使数组中的所有元素都大于或等于 k
,请你返回需要的 最少 操作次数。
示例 1:
输入:nums = [2,11,10,1,3], k = 10 输出:2 解释:第一次操作中,我们删除元素 1 和 2 ,然后添加 1 * 2 + 2 到 nums 中,nums 变为 [4, 11, 10, 3] 。 第二次操作中,我们删除元素 3 和 4 ,然后添加 3 * 2 + 4 到 nums 中,nums 变为 [10, 11, 10] 。 此时,数组中的所有元素都大于等于 10 ,所以我们停止操作。 使数组中所有元素都大于等于 10 需要的最少操作次数为 2 。
示例 2:
输入:nums = [1,1,2,4,9], k = 20 输出:4 解释:第一次操作后,nums 变为 [2, 4, 9, 3] 。 第二次操作后,nums 变为 [7, 4, 9] 。 第三次操作后,nums 变为 [15, 9] 。 第四次操作后,nums 变为 [33] 。 此时,数组中的所有元素都大于等于 20 ,所以我们停止操作。 使数组中所有元素都大于等于 20 需要的最少操作次数为 4 。
提示:
2 <= nums.length <= 2 * 105
1 <= nums[i] <= 109
1 <= k <= 109
- 输入保证答案一定存在,也就是说一定存在一个操作序列使数组中所有元素都大于等于
k
。
class Solution {
public:
int minOperations(vector<int>& nums, int k) {
int ans = 0;
priority_queue<long long, vector<long long>, greater<long long>>q;
for (auto x : nums)q.push(x);
while (q.size() > 1) {
long long a = q.top();
q.pop();
if (a >= k)return ans;
long long b = q.top();
q.pop();
q.push(a + a + b);
ans++;
}
return ans;
}
};
3083. 字符串及其反转中是否存在同一子字符串
给你一个字符串 s
,请你判断字符串 s
是否存在一个长度为 2
的子字符串,在 s
反转后的字符串中也出现。
如果存在这样的子字符串,返回 true
;如果不存在,返回 false
。
示例 1:
输入:s = "leetcode"
输出:true
解释:子字符串 "ee"
的长度为 2
,它也出现在 reverse(s) == "edocteel"
中。
示例 2:
输入:s = "abcba"
输出:true
解释:所有长度为 2
的子字符串 "ab"
、"bc"
、"cb"
、"ba"
也都出现在 reverse(s) == "abcba"
中。
示例 3:
输入:s = "abcd"
输出:false
解释:字符串 s
中不存在满足「在其反转后的字符串中也出现」且长度为 2
的子字符串。
提示:
1 <= s.length <= 100
- 字符串
s
仅由小写英文字母组成。
class Solution {
public:
bool isSubstringPresent(string s) {
string empt;
set<string>se;
for (int i = 1; i < s.length(); i++) {
if (s[i] == s[i - 1])return true;
if(se.find(empt + s[i] + s[i - 1])!=se.end())return true;
se.insert(empt + s[i - 1] + s[i]);
}
return false;
}
};
3086. 拾起 K 个 1 需要的最少行动次数
给你一个下标从 0 开始的二进制数组 nums
,其长度为 n
;另给你一个 正整数 k
以及一个 非负整数 maxChanges
。
Alice 在玩一个游戏,游戏的目标是让 Alice 使用 最少 数量的 行动 次数从 nums
中拾起 k
个 1 。游戏开始时,Alice 可以选择数组 [0, n - 1]
范围内的任何索引 aliceIndex
站立。如果 nums[aliceIndex] == 1
,Alice 会拾起一个 1 ,并且 nums[aliceIndex]
变成0
(这 不算 作一次行动)。之后,Alice 可以执行 任意数量 的 行动(包括零次),在每次行动中 Alice 必须 恰好 执行以下动作之一:
- 选择任意一个下标
j != aliceIndex
且满足nums[j] == 0
,然后将nums[j]
设置为1
。这个动作最多可以执行maxChanges
次。 - 选择任意两个相邻的下标
x
和y
(|x - y| == 1
)且满足nums[x] == 1
,nums[y] == 0
,然后交换它们的值(将nums[y] = 1
和nums[x] = 0
)。如果y == aliceIndex
,在这次行动后 Alice 拾起一个 1 ,并且nums[y]
变成0
。
返回 Alice 拾起 恰好 k
个 1 所需的 最少 行动次数。
示例 1:
输入:nums = [1,1,0,0,0,1,1,0,0,1], k = 3, maxChanges = 1
输出:3
解释:如果游戏开始时 Alice 在 aliceIndex == 1
的位置上,按照以下步骤执行每个动作,他可以利用 3
次行动拾取 3
个 1 :
- 游戏开始时 Alice 拾取了一个 1 ,
nums[1]
变成了0
。此时nums
变为[1,0,1,0,0,1,1,0,0,1]
。 - 选择
j == 2
并执行第一种类型的动作。nums
变为[1,0,1,0,0,1,1,0,0,1]
- 选择
x == 2
和y == 1
,并执行第二种类型的动作。nums
变为[1,1,0,0,0,1,1,0,0,1]
。由于y == aliceIndex
,Alice 拾取了一个 1 ,nums
变为[1,0,0,0,0,1,1,0,0,1]
。 - 选择
x == 0
和y == 1
,并执行第二种类型的动作。nums
变为[0,1,0,0,0,1,1,0,0,1]
。由于y == aliceIndex
,Alice 拾取了一个 1 ,nums
变为[0,0,0,0,0,1,1,0,0,1]
。
请注意,Alice 也可能执行其他的 3
次行动序列达成拾取 3
个 1 。
示例 2:
输入:nums = [0,0,0,0], k = 2, maxChanges = 3
输出:4
解释:如果游戏开始时 Alice 在 aliceIndex == 0
的位置上,按照以下步骤执行每个动作,他可以利用 4
次行动拾取 2
个 1 :
- 选择
j == 1
并执行第一种类型的动作。nums
变为[0,1,0,0]
。 - 选择
x == 1
和y == 0
,并执行第二种类型的动作。nums
变为[1,0,0,0]
。由于y == aliceIndex
,Alice 拾起了一个 1 ,nums
变为[0,0,0,0]
。 - 再次选择
j == 1
并执行第一种类型的动作。nums
变为[0,1,0,0]
。 - 再次选择
x == 1
和y == 0
,并执行第二种类型的动作。nums
变为[1,0,0,0]
。由于y == aliceIndex
,Alice 拾起了一个 1 ,nums
变为[0,0,0,0]
。
提示:
2 <= n <= 105
0 <= nums[i] <= 1
1 <= k <= 105
0 <= maxChanges <= 105
maxChanges + sum(nums) >= k
class Solution {
public:
long long minimumMoves(vector<int>& nums, int k, int maxChanges) {
int loc = near3(nums);
int s = s3(nums, loc);
if (k == 1)return s?0:2;
if (k <= s) return k - nums[loc];
if (k <= s + maxChanges)return k * 2 - s - nums[loc];
return minimumMoves(nums, k - maxChanges) + maxChanges * 2;
}
long long minimumMoves(vector<int>& nums, int k) // maxChanges=0
{
deque<int>q;
long long s = 0, ans = 0;
for (int i = 0; i < nums.size(); i++)
{
if (nums[i] == 0)continue;
q.push_back(i);
if (q.size() == k) {
int m = q[k / 2];
for (int i = 0; i < k; i++) {
s += abs(q[i] - m);
}
ans = s;
}
if (q.size() > k) {
s += abs(q[k] - q[(k + 1) / 2]) - abs(q[0] - q[k / 2]);
ans = min(ans, s);
q.pop_front();
}
}
return ans;
}
int s3(vector<int>& nums, int id)
{
int s = nums[id];
if (id)s += nums[id - 1];
if (id + 1 < nums.size())s += nums[id + 1];
return s;
}
int near3(vector<int>& nums)
{
int loc = 0, smax = 0;
for (int i = 0; i < nums.size(); i++) {
int s = s3(nums, i);
if (smax < s)smax = s, loc = i;
if (smax == s && nums[i])loc = i;
}
return loc;
}
};
3099. 哈沙德数
如果一个整数能够被其各个数位上的数字之和整除,则称之为 哈沙德数(Harshad number)。给你一个整数 x
。如果 x
是 哈沙德数 ,则返回 x
各个数位上的数字之和,否则,返回 -1
。
示例 1:
输入: x = 18
输出: 9
解释:
x
各个数位上的数字之和为 9
。18
能被 9
整除。因此 18
是哈沙德数,答案是 9
。
示例 2:
输入: x = 23
输出: -1
解释:
x
各个数位上的数字之和为 5
。23
不能被 5
整除。因此 23
不是哈沙德数,答案是 -1
。
提示:
1 <= x <= 100
class Solution {
public:
int sumOfTheDigitsOfHarshadNumber(int x) {
int s=0,y=x;
while(y)s+=y%10,y/=10;
if(x%s==0)return s;
return -1;
}
};
3100. 换水问题 II
给你两个整数 numBottles
和 numExchange
。
numBottles
代表你最初拥有的满水瓶数量。在一次操作中,你可以执行以下操作之一:
- 喝掉任意数量的满水瓶,使它们变成空水瓶。
- 用
numExchange
个空水瓶交换一个满水瓶。然后,将numExchange
的值增加 1 。
注意,你不能使用相同的 numExchange
值交换多批空水瓶。例如,如果 numBottles == 3
并且 numExchange == 1
,则不能用 3
个空水瓶交换成 3
个满水瓶。
返回你 最多 可以喝到多少瓶水。
示例 1:
输入:numBottles = 13, numExchange = 6 输出:15 解释:上表显示了满水瓶的数量、空水瓶的数量、numExchange 的值,以及累计喝掉的水瓶数量。
示例 2:
输入:numBottles = 10, numExchange = 3 输出:13 解释:上表显示了满水瓶的数量、空水瓶的数量、numExchange 的值,以及累计喝掉的水瓶数量。
提示:
1 <= numBottles <= 100
1 <= numExchange <= 100
class Solution {
public:
int maxBottlesDrunk(int numBottles, int numExchange) {
int ans=numBottles,s=numBottles;
while(s>=numExchange){
s-=numExchange++-1;
ans++;
}
return ans;
}
};
3110. 字符串的分数
给你一个字符串 s
。一个字符串的 分数 定义为相邻字符 ASCII 码差值绝对值的和。
请你返回 s
的 分数 。
示例 1:
输入:s = "hello"
输出:13
解释:
s
中字符的 ASCII 码分别为:'h' = 104
,'e' = 101
,'l' = 108
,'o' = 111
。所以 s
的分数为 |104 - 101| + |101 - 108| + |108 - 108| + |108 - 111| = 3 + 7 + 0 + 3 = 13
。
示例 2:
输入:s = "zaz"
输出:50
解释:
s
中字符的 ASCII 码分别为:'z' = 122
,'a' = 97
。所以 s
的分数为 |122 - 97| + |97 - 122| = 25 + 25 = 50
。
提示:
2 <= s.length <= 100
s
只包含小写英文字母。
class Solution {
public:
int scoreOfString(string s) {
char c=s[0];
int ans=0;
for(auto ch:s)ans+=abs(ch-c),c=ch;
return ans;
}
};
3111. 覆盖所有点的最少矩形数目
给你一个二维整数数组 point
,其中 points[i] = [xi, yi]
表示二维平面内的一个点。同时给你一个整数 w
。你需要用矩形 覆盖所有 点。
每个矩形的左下角在某个点 (x1, 0)
处,且右上角在某个点 (x2, y2)
处,其中 x1 <= x2
且 y2 >= 0
,同时对于每个矩形都 必须 满足 x2 - x1 <= w
。
如果一个点在矩形内或者在边上,我们说这个点被矩形覆盖了。
请你在确保每个点都 至少 被一个矩形覆盖的前提下,最少 需要多少个矩形。
注意:一个点可以被多个矩形覆盖。
示例 1:
输入:points = [[2,1],[1,0],[1,4],[1,8],[3,5],[4,6]], w = 1
输出:2
解释:
上图展示了一种可行的矩形放置方案:
- 一个矩形的左下角在
(1, 0)
,右上角在(2, 8)
。 - 一个矩形的左下角在
(3, 0)
,右上角在(4, 8)
。
示例 2:
输入:points = [[0,0],[1,1],[2,2],[3,3],[4,4],[5,5],[6,6]], w = 2
输出:3
解释:
上图展示了一种可行的矩形放置方案:
- 一个矩形的左下角在
(0, 0)
,右上角在(2, 2)
。 - 一个矩形的左下角在
(3, 0)
,右上角在(5, 5)
。 - 一个矩形的左下角在
(6, 0)
,右上角在(6, 6)
。
示例 3:
输入:points = [[2,3],[1,2]], w = 0
输出:2
解释:
上图展示了一种可行的矩形放置方案:
- 一个矩形的左下角在
(1, 0)
,右上角在(1, 2)
。 - 一个矩形的左下角在
(2, 0)
,右上角在(2, 3)
。
提示:
1 <= points.length <= 105
points[i].length == 2
0 <= xi == points[i][0] <= 109
0 <= yi == points[i][1] <= 109
0 <= w <= 109
- 所有点坐标
(xi, yi)
互不相同。
class Solution {
public:
int minRectanglesToCoverPoints(vector<vector<int>>& points, int w) {
vector<int>v;
for (auto vi : points)v.push_back(vi[0]);
sort(v.begin(), v.end());
int x = v[0], ans = 1;
for (int i = 0; i < v.size(); i++) {
if (v[i] - x > w)ans++, x = v[i];
}
return ans;
}
};
3115. 质数的最大距离
3116. 单面值组合的第 K 小金额
3120. 统计特殊字母的数量 I
给你一个字符串 word
。如果 word
中同时存在某个字母的小写形式和大写形式,则称这个字母为 特殊字母 。
返回 word
中 特殊字母 的数量。
示例 1:
输入:word = "aaAbcBC"
输出:3
解释:
word
中的特殊字母是 'a'
、'b'
和 'c'
。
示例 2:
输入:word = "abc"
输出:0
解释:
word
中不存在大小写形式同时出现的字母。
示例 3:
输入:word = "abBCab"
输出:1
解释:
word
中唯一的特殊字母是 'b'
。
提示:
1 <= word.length <= 50
word
仅由小写和大写英文字母组成。
class Solution {
public:
int numberOfSpecialChars(string word) {
int num[52];
for(int i=0;i<52;i++)num[i]=0;
for(auto c:word){
if(c>='a'&&c<='z')num[c-'a']++;
if(c>='A'&&c<='Z')num[c-'A'+26]++;
}
int ans = 0;
for(int i=0;i<26;i++){
if(num[i]>0 && num[i+26]>0)ans++;
}
return ans;
}
};
3121. 统计特殊字母的数量 II
给你一个字符串 word
。如果 word
中同时出现某个字母 c
的小写形式和大写形式,并且 每个 小写形式的 c
都出现在第一个大写形式的 c
之前,则称字母 c
是一个 特殊字母 。
返回 word
中 特殊字母 的数量。
示例 1:
输入:word = "aaAbcBC"
输出:3
解释:
特殊字母是 'a'
、'b'
和 'c'
。
示例 2:
输入:word = "abc"
输出:0
解释:
word
中不存在特殊字母。
示例 3:
输入:word = "AbBCab"
输出:0
解释:
word
中不存在特殊字母。
提示:
1 <= word.length <= 2 * 105
word
仅由小写和大写英文字母组成。
class Solution {
public:
int numberOfSpecialChars(string word) {
int num[52];
for(int i=0;i<52;i++)num[i]=0;
for(auto c:word){
if(c>='a'&&c<='z'){
num[c-'a']++;
if(num[c-'a'+26])num[c-'a']=-1234567;
}
if(c>='A'&&c<='Z')num[c-'A'+26]++;
}
int ans = 0;
for(int i=0;i<26;i++){
if(num[i]>0 && num[i+26]>0)ans++;
}
return ans;
}
};
3127. 构造相同颜色的正方形
给你一个二维 3 x 3
的矩阵 grid
,每个格子都是一个字符,要么是 'B'
,要么是 'W'
。字符 'W'
表示白色,字符 'B'
表示黑色。
你的任务是改变 至多一个 格子的颜色,使得矩阵中存在一个 2 x 2
颜色完全相同的正方形。
如果可以得到一个相同颜色的 2 x 2
正方形,那么返回 true
,否则返回 false
。
示例 1:
输入:grid = [["B","W","B"],["B","W","W"],["B","W","B"]]
输出:true
解释:
修改 grid[0][2]
的颜色,可以满足要求。
示例 2:
输入:grid = [["B","W","B"],["W","B","W"],["B","W","B"]]
输出:false
解释:
只改变一个格子颜色无法满足要求。
示例 3:
输入:grid = [["B","W","B"],["B","W","W"],["B","W","W"]]
输出:true
解释:
grid
已经包含一个 2 x 2
颜色相同的正方形了。
提示:
grid.length == 3
grid[i].length == 3
grid[i][j]
要么是'W'
,要么是'B'
。
class Solution {
public:
bool canMakeSquare(vector<vector<char>>& grid) {
for(int i=1;i<grid.size();i++){
for(int j=1;j<grid[0].size();j++){
int s=0;
if(grid[i][j]=='B')s++;
if(grid[i][j-1]=='B')s++;
if(grid[i-1][j]=='B')s++;
if(grid[i-1][j-1]=='B')s++;
if(s!=2)return true;
}
}
return false;
}
};
3131. 找出与数组相加的整数 I
给你两个长度相等的数组 nums1
和 nums2
。
数组 nums1
中的每个元素都与变量 x
所表示的整数相加。如果 x
为负数,则表现为元素值的减少。
在与 x
相加后,nums1
和 nums2
相等 。当两个数组中包含相同的整数,并且这些整数出现的频次相同时,两个数组 相等 。
返回整数 x
。
示例 1:
输入:nums1 = [2,6,4], nums2 = [9,7,5]
输出:3
解释:
与 3 相加后,nums1
和 nums2
相等。
示例 2:
输入:nums1 = [10], nums2 = [5]
输出:-5
解释:
与 -5
相加后,nums1
和 nums2
相等。
示例 3:
输入:nums1 = [1,1,1,1], nums2 = [1,1,1,1]
输出:0
解释:
与 0 相加后,nums1
和 nums2
相等。
提示:
1 <= nums1.length == nums2.length <= 100
0 <= nums1[i], nums2[i] <= 1000
- 测试用例以这样的方式生成:存在一个整数
x
,使得nums1
中的每个元素都与x
相加后,nums1
与nums2
相等。
class Solution {
public:
int addedInteger(vector<int>& nums1, vector<int>& nums2) {
int m1=nums1[0],m2=nums2[0];
for(auto x:nums1)m1=max(m1,x);
for(auto x:nums2)m2=max(m2,x);
return m2-m1;
}
};
3132. 找出与数组相加的整数 II
3133. 数组最后一个元素的最小值
给你两个整数 n
和 x
。你需要构造一个长度为 n
的 正整数 数组 nums
,对于所有 0 <= i < n - 1
,满足 nums[i + 1]
大于 nums[i]
,并且数组 nums
中所有元素的按位 AND
运算结果为 x
。
返回 nums[n - 1]
可能的 最小 值。
示例 1:
输入:n = 3, x = 4
输出:6
解释:
数组 nums
可以是 [4,5,6]
,最后一个元素为 6
。
示例 2:
输入:n = 2, x = 7
输出:15
解释:
数组 nums
可以是 [7,15]
,最后一个元素为 15
。
提示:
1 <= n, x <= 108
class Solution {
public:
long long minEnd(int n, int x) {
long long s = x, one = 1;
int m = n - 1;
for (int i = 0; m; i++) {
if (s&(one << i))continue;
if (m & 1)s |= (one << i);
m >>= 1;
}
return s;
}
};
3142. 判断矩阵是否满足条件
给你一个大小为 m x n
的二维矩阵 grid
。你需要判断每一个格子 grid[i][j]
是否满足:
- 如果它下面的格子存在,那么它需要等于它下面的格子,也就是
grid[i][j] == grid[i + 1][j]
。 - 如果它右边的格子存在,那么它需要不等于它右边的格子,也就是
grid[i][j] != grid[i][j + 1]
。
如果 所有 格子都满足以上条件,那么返回 true
,否则返回 false
。
示例 1:
输入:grid = [[1,0,2],[1,0,2]]
输出:true
解释:
网格图中所有格子都符合条件。
示例 2:
输入:grid = [[1,1,1],[0,0,0]]
输出:false
解释:
示例 3:
输入:grid = [[1],[2],[3]]
输出:false
解释:
同一列中的格子值不相等。
提示:
1 <= n, m <= 10
0 <= grid[i][j] <= 9
class Solution {
public:
bool satisfiesConditions(vector<vector<int>>& grid) {
int r=grid.size(),c=grid[0].size();
for(int i=0;i<r;i++){
for(int j=1;j<c;j++)if(grid[i][j]==grid[i][j-1])return false;
}
for(int i=1;i<r;i++){
for(int j=0;j<c;j++)if(grid[i][j]!=grid[i-1][j])return false;
}
return true;
}
};
3143. 正方形中的最多点数
给你一个二维数组 points
和一个字符串 s
,其中 points[i]
表示第 i
个点的坐标,s[i]
表示第 i
个点的 标签 。
如果一个正方形的中心在 (0, 0)
,所有边都平行于坐标轴,且正方形内 不 存在标签相同的两个点,那么我们称这个正方形是 合法 的。
请你返回 合法 正方形中可以包含的 最多 点数。
注意:
- 如果一个点位于正方形的边上或者在边以内,则认为该点位于正方形内。
- 正方形的边长可以为零。
示例 1:
输入:points = [[2,2],[-1,-2],[-4,4],[-3,1],[3,-3]], s = "abdca"
输出:2
解释:
边长为 4 的正方形包含两个点 points[0]
和 points[1]
。
示例 2:
输入:points = [[1,1],[-2,-2],[-2,2]], s = "abb"
输出:1
解释:
边长为 2 的正方形包含 1 个点 points[0]
。
示例 3:
输入:points = [[1,1],[-1,-1],[2,-2]], s = "ccd"
输出:0
解释:
任何正方形都无法只包含 points[0]
和 points[1]
中的一个点,所以合法正方形中都不包含任何点。
提示:
1 <= s.length, points.length <= 105
points[i].length == 2
-109 <= points[i][0], points[i][1] <= 109
s.length == points.length
points
中的点坐标互不相同。s
只包含小写英文字母。
class Solution {
public:
int maxPointsInsideSquare(vector<vector<int>>& points, string s) {
vector<int>v,v2;
for(auto vi:points)v.push_back(max(abs(vi[0]),abs(vi[1])));
for(auto c:s)v2.push_back(c);
SortExtend(v,v2);
map<int,int>m;
int maxSize = v[v.size()-1];
for(int i=0;i<v.size();i++){
if(m[v2[i]]){
maxSize=v[i]-1;
break;
}
m[v2[i]]=1;
}
int ans=0;
for(auto x:v)if(x<=maxSize)ans++;
return ans;
}
};
3146. 两个字符串的排列差
给你两个字符串 s
和 t
,每个字符串中的字符都不重复,且 t
是 s
的一个排列。
排列差 定义为 s
和 t
中每个字符在两个字符串中位置的绝对差值之和。
返回 s
和 t
之间的 排列差 。
示例 1:
输入:s = "abc", t = "bac"
输出:2
解释:
对于 s = "abc"
和 t = "bac"
,排列差是:
"a"
在s
中的位置与在t
中的位置之差的绝对值。"b"
在s
中的位置与在t
中的位置之差的绝对值。"c"
在s
中的位置与在t
中的位置之差的绝对值。
即,s
和 t
的排列差等于 |0 - 1| + |1 - 0| + |2 - 2| = 2
。
示例 2:
输入:s = "abcde", t = "edbac"
输出:12
解释: s
和 t
的排列差等于 |0 - 3| + |1 - 2| + |2 - 4| + |3 - 1| + |4 - 0| = 12
。
提示:
1 <= s.length <= 26
- 每个字符在
s
中最多出现一次。 t
是s
的一个排列。s
仅由小写英文字母组成。
class Solution {
public:
int findPermutationDifference(string s, string t) {
map<char,int>m;
int id=0,ans=0;
for(auto c:s)m[c]=id++;
for(int i=0;i<id;i++)ans+=abs(m[t[i]]-i);
return ans;
}
};
3151. 特殊数组 I
如果数组的每一对相邻元素都是两个奇偶性不同的数字,则该数组被认为是一个 特殊数组 。
你有一个整数数组 nums
。如果 nums
是一个 特殊数组 ,返回 true
,否则返回 false
。
示例 1:
输入:nums = [1]
输出:true
解释:
只有一个元素,所以答案为 true
。
示例 2:
输入:nums = [2,1,4]
输出:true
解释:
只有两对相邻元素: (2,1)
和 (1,4)
,它们都包含了奇偶性不同的数字,因此答案为 true
。
示例 3:
输入:nums = [4,3,1,6]
输出:false
解释:
nums[1]
和 nums[2]
都是奇数。因此答案为 false
。
提示:
1 <= nums.length <= 100
1 <= nums[i] <= 100
class Solution {
public:
bool isArraySpecial(vector<int>& nums) {
for(int i=1;i<nums.size();i++)if((nums[i]&1)==(nums[i-1]&1))return false;
return true;
}
};
3152. 特殊数组 II
如果数组的每一对相邻元素都是两个奇偶性不同的数字,则该数组被认为是一个 特殊数组 。
你有一个整数数组 nums
和一个二维整数矩阵 queries
,对于 queries[i] = [fromi, toi]
,请你帮助你检查
子数组
nums[fromi..toi]
是不是一个 特殊数组 。
返回布尔数组 answer
,如果 nums[fromi..toi]
是特殊数组,则 answer[i]
为 true
,否则,answer[i]
为 false
。
示例 1:
输入:nums = [3,4,1,2,6], queries = [[0,4]]
输出:[false]
解释:
子数组是 [3,4,1,2,6]
。2 和 6 都是偶数。
示例 2:
输入:nums = [4,3,1,6], queries = [[0,2],[2,3]]
输出:[false,true]
解释:
- 子数组是
[4,3,1]
。3 和 1 都是奇数。因此这个查询的答案是false
。 - 子数组是
[1,6]
。只有一对:(1,6)
,且包含了奇偶性不同的数字。因此这个查询的答案是true
。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 105
1 <= queries.length <= 105
queries[i].length == 2
0 <= queries[i][0] <= queries[i][1] <= nums.length - 1
class Solution {
public:
vector<bool> isArraySpecial(vector<int>& nums, vector<vector<int>>& queries) {
vector<int>id(nums.size());
int low=0;
for(int i=1;i<nums.size();i++){
if((nums[i]&1)==(nums[i-1]&1)){
for(int j=low;j<i;j++)id[j]=i;
low=i;
}
}
for(int j=low;j<nums.size();j++)id[j]=nums.size();
vector<bool>ans;
for(auto v:queries)ans.push_back(v[1]<id[v[0]]);
return ans;
}
};
3153. 所有数对中数位差之和
你有一个数组 nums
,它只包含 正 整数,所有正整数的数位长度都 相同 。
两个整数的 数位差 指的是两个整数 相同 位置上不同数字的数目。
请你返回 nums
中 所有 整数对里,数位差之和。
示例 1:
输入:nums = [13,23,12]
输出:4
解释:
计算过程如下:
- 13 和 23 的数位差为 1 。
- 13 和 12 的数位差为 1 。
- 23 和 12 的数位差为 2 。
所以所有整数数对的数位差之和为 1 + 1 + 2 = 4
。
示例 2:
输入:nums = [10,10,10,10]
输出:0
解释:
数组中所有整数都相同,所以所有整数数对的数位不同之和为 0 。
提示:
2 <= nums.length <= 105
1 <= nums[i] < 109
nums
中的整数都有相同的数位长度。
class Solution {
public:
long long sumDigitDifferences(vector<int>& nums) {
vector<int>v(10);
long long ans=0;
while(nums[0]){
for(int i=0;i<10;i++)v[i]=0;
for(auto &x:nums)v[x%10]++,x/=10;
ans+=sumOneBit(v,nums.size());
}
return ans;
}
long long sumOneBit(vector<int>v,long long s)
{
long long ans=0;
for(auto x:v)ans+=x*(s-x);
return ans/2;
}
};
3159. 查询数组中元素的出现位置
给你一个整数数组 nums
,一个整数数组 queries
和一个整数 x
。
对于每个查询 queries[i]
,你需要找到 nums
中第 queries[i]
个 x
的位置,并返回它的下标。如果数组中 x
的出现次数少于 queries[i]
,该查询的答案为 -1 。
请你返回一个整数数组 answer
,包含所有查询的答案。
示例 1:
输入:nums = [1,3,1,7], queries = [1,3,2,4], x = 1
输出:[0,-1,2,-1]
解释:
- 第 1 个查询,第一个 1 出现在下标 0 处。
- 第 2 个查询,
nums
中只有两个 1 ,所以答案为 -1 。 - 第 3 个查询,第二个 1 出现在下标 2 处。
- 第 4 个查询,
nums
中只有两个 1 ,所以答案为 -1 。
示例 2:
输入:nums = [1,2,3], queries = [10], x = 5
输出:[-1]
解释:
- 第 1 个查询,
nums
中没有 5 ,所以答案为 -1 。
提示:
1 <= nums.length, queries.length <= 105
1 <= queries[i] <= 105
1 <= nums[i], x <= 104
class Solution {
public:
vector<int> occurrencesOfElement(vector<int>& nums, vector<int>& queries, int x) {
map<int, vector<int>>m;
for (int i = 0; i < nums.size(); i++) {
m[nums[i]].push_back(i);
}
auto v = m[x];
vector<int>ans;
for (auto q : queries) {
if (q > v.size())ans.push_back(-1);
else ans.push_back(v[q-1]);
}
return ans;
}
};
3162. 优质数对的总数 I
给你两个整数数组 nums1
和 nums2
,长度分别为 n
和 m
。同时给你一个正整数 k
。
如果 nums1[i]
可以除尽 nums2[j] * k
,则称数对 (i, j)
为 优质数对(0 <= i <= n - 1
, 0 <= j <= m - 1
)。
返回 优质数对 的总数。
示例 1:
输入:nums1 = [1,3,4], nums2 = [1,3,4], k = 1
输出:5
解释:
5个优质数对分别是 (0, 0)
, (1, 0)
, (1, 1)
, (2, 0)
, 和 (2, 2)
。
示例 2:
输入:nums1 = [1,2,4,12], nums2 = [2,4], k = 3
输出:2
解释:
2个优质数对分别是 (3, 0)
和 (3, 1)
。
提示:
1 <= n, m <= 50
1 <= nums1[i], nums2[j] <= 50
1 <= k <= 50
class Solution {
public:
int numberOfPairs(vector<int>& nums1, vector<int>& nums2, int k) {
int ans=0;
for(auto x:nums1){
for(auto y:nums2){
if(x/y/k*k*y==x)ans++;
}
}
return ans;
}
};
3176. 求出最长好子序列 I
给你一个整数数组 nums
和一个 非负 整数 k
。如果一个整数序列 seq
满足在下标范围 [0, seq.length - 2]
中 最多只有 k
个下标 i
满足 seq[i] != seq[i + 1]
,那么我们称这个整数序列为 好 序列。
请你返回 nums
中 好
子序列
的最长长度。
示例 1:
输入:nums = [1,2,1,1,3], k = 2
输出:4
解释:
最长好子序列为 [1,2,1,1,3]
。
示例 2:
输入:nums = [1,2,3,4,5,1], k = 0
输出:2
解释:
最长好子序列为 [1,2,3,4,5,1]
。
提示:
1 <= nums.length <= 500
1 <= nums[i] <= 109
0 <= k <= min(nums.length, 25)
class Solution {
public:
int maximumLength(vector<int>& nums, int k) {
map<int, map<int, int>>m;
map<int, int>id;
map<int, int>ans;
for (int i = 0; i < nums.size(); i++) {
bool flag = (id.find(nums[i]) != id.end());
for (int j = 0; j <= k; j++) {
m[i][j] = max(m[i][j], (j ? ans[j - 1] : 0) + 1);
if (flag)m[i][j] = max(m[i][j], m[id[nums[i]]][j] + 1);
}
for (int j = 0; j <= k; j++) {
ans[j] = max(ans[j], m[i][j]);
}
id[nums[i]] = i;
}
int r = 0;
for (auto mi : ans)r = max(r, mi.second);
return r;
}
};
3177. 求出最长好子序列 II
给你一个整数数组 nums
和一个 非负 整数 k
。如果一个整数序列 seq
满足在范围下标范围 [0, seq.length - 2]
中存在 不超过 k
个下标 i
满足 seq[i] != seq[i + 1]
,那么我们称这个整数序列为 好 序列。
请你返回 nums
中 好 子序列 的最长长度
示例 1:
输入:nums = [1,2,1,1,3], k = 2
输出:4
解释:
最长好子序列为 [1,2,1,1,3]
。
示例 2:
输入:nums = [1,2,3,4,5,1], k = 0
输出:2
解释:
最长好子序列为 [1,2,3,4,5,1]
。
提示:
1 <= nums.length <= 5 * 103
1 <= nums[i] <= 109
0 <= k <= min(50, nums.length)
class Solution {
public:
int maximumLength(vector<int>& nums, int k) {
unordered_map<int, unordered_map<int, int>>m;
map<int, int>id;
map<int, int>ans;
for (int i = 0; i < nums.size(); i++) {
bool flag = (id.find(nums[i]) != id.end());
for (int j = 0; j <= k; j++) {
m[i][j] = max(m[i][j], (j ? ans[j - 1] : 0) + 1);
if (flag)m[i][j] = max(m[i][j], m[id[nums[i]]][j] + 1);
}
for (int j = 0; j <= k; j++) {
ans[j] = max(ans[j], m[i][j]);
}
id[nums[i]] = i;
}
int r = 0;
for (auto mi : ans)r = max(r, mi.second);
return r;
}
};
3180. 执行操作可获得的最大总奖励 I
给你一个整数数组 rewardValues
,长度为 n
,代表奖励的值。
最初,你的总奖励 x
为 0,所有下标都是 未标记 的。你可以执行以下操作 任意次 :
- 从区间
[0, n - 1]
中选择一个 未标记 的下标i
。 - 如果
rewardValues[i]
大于 你当前的总奖励x
,则将rewardValues[i]
加到x
上(即x = x + rewardValues[i]
),并 标记 下标i
。
以整数形式返回执行最优操作能够获得的 最大 总奖励。
示例 1:
输入:rewardValues = [1,1,3,3]
输出:4
解释:
依次标记下标 0 和 2,总奖励为 4,这是可获得的最大值。
示例 2:
输入:rewardValues = [1,6,4,3,2]
输出:11
解释:
依次标记下标 0、2 和 1。总奖励为 11,这是可获得的最大值。
提示:
1 <= rewardValues.length <= 2000
1 <= rewardValues[i] <= 2000
class Solution {
public:
int maxTotalReward(vector<int>& v) {
sort(v.begin(), v.end());
set<int>s1, s2;
s2.insert(0);
for (auto x : v) {
s1 = s2;
for (auto y : s1) {
if (y >= x)break;
s2.insert(y + x);
}
}
return *s2.rbegin();
}
};
3185. 构成整天的下标对数目 II
给你一个整数数组 hours
,表示以 小时 为单位的时间,返回一个整数,表示满足 i < j
且 hours[i] + hours[j]
构成 整天 的下标对 i
, j
的数目。
整天 定义为时间持续时间是 24 小时的 整数倍 。
例如,1 天是 24 小时,2 天是 48 小时,3 天是 72 小时,以此类推。
示例 1:
输入: hours = [12,12,30,24,24]
输出: 2
解释:
构成整天的下标对分别是 (0, 1)
和 (3, 4)
。
示例 2:
输入: hours = [72,48,24,3]
输出: 3
解释:
构成整天的下标对分别是 (0, 1)
、(0, 2)
和 (1, 2)
。
提示:
1 <= hours.length <= 5 * 105
1 <= hours[i] <= 109
class Solution {
public:
long long countCompleteDayPairs(vector<int>& hours) {
map<int,long long>m;
for(auto x:hours)m[x%24]++;
long long ans=m[0]*(m[0]-1)/2+m[12]*(m[12]-1)/2;
for(int i=1;i<12;i++)ans+=m[i]*m[24-i];
return ans;
}
};
3191. 使二进制数组全部等于 1 的最少操作次数 I
给你一个二进制数组 nums
。
你可以对数组执行以下操作 任意 次(也可以 0 次):
- 选择数组中 任意连续 3 个元素,并将它们 全部反转 。
反转 一个元素指的是将它的值从 0 变 1 ,或者从 1 变 0 。
请你返回将 nums
中所有元素变为 1 的 最少 操作次数。如果无法全部变成 1 ,返回 -1 。
示例 1:
输入:nums = [0,1,1,1,0,0]
输出:3
解释:
我们可以执行以下操作:
- 选择下标为 0 ,1 和 2 的元素并反转,得到
nums = [1,0,0,1,0,0]
。 - 选择下标为 1 ,2 和 3 的元素并反转,得到
nums = [1,1,1,0,0,0]
。 - 选择下标为 3 ,4 和 5 的元素并反转,得到
nums = [1,1,1,1,1,1]
。
示例 2:
输入:nums = [0,1,1,1]
输出:-1
解释:
无法将所有元素都变为 1 。
提示:
3 <= nums.length <= 105
0 <= nums[i] <= 1
class Solution {
public:
int minOperations(vector<int>& nums) {
int ans=0;
for(int i=0;i<nums.size()-2;i++){
if(nums[i]==0)nums[i]^=1,nums[i+1]^=1,nums[i+2]^=1,ans++;
}
return (nums[nums.size()-1] & nums[nums.size()-2]) ?ans : -1;
}
};
3192. 使二进制数组全部等于 1 的最少操作次数 II
给你一个二进制数组 nums
。
你可以对数组执行以下操作 任意 次(也可以 0 次):
- 选择数组中 任意 一个下标
i
,并将从下标i
开始一直到数组末尾 所有 元素 反转 。
反转 一个元素指的是将它的值从 0 变 1 ,或者从 1 变 0 。
请你返回将 nums
中所有元素变为 1 的 最少 操作次数。
示例 1:
输入:nums = [0,1,1,0,1]
输出:4
解释:
我们可以执行以下操作:
- 选择下标
i = 1
执行操作,得到nums = [0,0,0,1,0]
。 - 选择下标
i = 0
执行操作,得到nums = [1,1,1,0,1]
。 - 选择下标
i = 4
执行操作,得到nums = [1,1,1,0,0]
。 - 选择下标
i = 3
执行操作,得到nums = [1,1,1,1,1]
。
示例 2:
输入:nums = [1,0,0,0]
输出:1
解释:
我们可以执行以下操作:
- 选择下标
i = 1
执行操作,得到nums = [1,1,1,1]
。
提示:
1 <= nums.length <= 105
0 <= nums[i] <= 1
class Solution {
public:
int minOperations(vector<int>& nums) {
int a = 1, ans = 0;
for (auto x : nums) {
if (x != a)ans++;
a = x;
}
return ans;
}
};
3195. 包含所有 1 的最小矩形面积 I
给你一个二维 二进制 数组 grid
。请你找出一个边在水平方向和竖直方向上、面积 最小 的矩形,并且满足 grid
中所有的 1 都在矩形的内部。
返回这个矩形可能的 最小 面积。
示例 1:
输入: grid = [[0,1,0],[1,0,1]]
输出: 6
解释:
这个最小矩形的高度为 2,宽度为 3,因此面积为 2 * 3 = 6
。
示例 2:
输入: grid = [[0,0],[1,0]]
输出: 1
解释:
这个最小矩形的高度和宽度都是 1,因此面积为 1 * 1 = 1
。
提示:
1 <= grid.length, grid[i].length <= 1000
grid[i][j]
是 0 或 1。- 输入保证
grid
中至少有一个 1 。
class Solution {
public:
int minimumArea(vector<vector<int>>& grid) {
int r = grid.size(), c = grid[0].size();
int x1 = r, x2 = 0, y1 = c, y2 = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j])x1 = min(x1, i), x2 = max(x2, i), y1 = min(y1, j), y2 = max(y2, j);
}
}
return (x2 - x1 + 1)*(y2 - y1 + 1);
}
};
3206. 交替组 I
给你一个整数数组 colors
,它表示一个由红色和蓝色瓷砖组成的环,第 i
块瓷砖的颜色为 colors[i]
:
colors[i] == 0
表示第i
块瓷砖的颜色是 红色 。colors[i] == 1
表示第i
块瓷砖的颜色是 蓝色 。
环中连续 3 块瓷砖的颜色如果是 交替 颜色(也就是说中间瓷砖的颜色与它 左边 和 右边 的颜色都不同),那么它被称为一个 交替 组。
请你返回 交替 组的数目。
注意 ,由于 colors
表示一个 环 ,第一块 瓷砖和 最后一块 瓷砖是相邻的。
示例 1:
输入:colors = [1,1,1]
输出:0
解释:
示例 2:
输入:colors = [0,1,0,0,1]
输出:3
解释:
交替组包括:
提示:
3 <= colors.length <= 100
0 <= colors[i] <= 1
class Solution {
public:
int numberOfAlternatingGroups(vector<int>& colors) {
int n = colors.size(), ans = 0;
for (int i = 0; i < n; i++) {
if (colors[i] != colors[(i + 1) % n] && colors[i] != colors[(i - 1 + n) % n])ans++;
}
return ans;
}
};
3208. 交替组 II
给你一个整数数组 colors
和一个整数 k
,colors
表示一个由红色和蓝色瓷砖组成的环,第 i
块瓷砖的颜色为 colors[i]
:
colors[i] == 0
表示第i
块瓷砖的颜色是 红色 。colors[i] == 1
表示第i
块瓷砖的颜色是 蓝色 。
环中连续 k
块瓷砖的颜色如果是 交替 颜色(也就是说除了第一块和最后一块瓷砖以外,中间瓷砖的颜色与它 左边 和 右边 的颜色都不同),那么它被称为一个 交替 组。
请你返回 交替 组的数目。
注意 ,由于 colors
表示一个 环 ,第一块 瓷砖和 最后一块 瓷砖是相邻的。
示例 1:
输入:colors = [0,1,0,1,0], k = 3
输出:3
解释:
交替组包括:
示例 2:
输入:colors = [0,1,0,0,1,0,1], k = 6
输出:2
解释:
交替组包括:
示例 3:
输入:colors = [1,1,0,1], k = 4
输出:0
解释:
提示:
3 <= colors.length <= 105
0 <= colors[i] <= 1
3 <= k <= colors.length
class Solution {
public:
int numberOfAlternatingGroups(vector<int>& v, int k) {
int n = v.size();
for (int i = 0; i < k-1; i++)v.push_back(v[i]);
int s = 0, ans = 0;
for (int i = 1; i < v.size(); i++) {
if (v[i] != v[i - 1])s++;
if (i >= k && v[i - k + 1] != v[i - k])s--;
if (s == k - 1)ans++;
}
return ans;
}
};
3211. 生成不含相邻零的二进制字符串
给你一个正整数 n
。
如果一个二进制字符串 x
的所有长度为 2 的
子字符串
中包含 至少 一个 "1"
,则称 x
是一个 有效 字符串。
返回所有长度为 n
的 有效 字符串,可以以任意顺序排列。
示例 1:
输入: n = 3
输出: ["010","011","101","110","111"]
解释:
长度为 3 的有效字符串有:"010"
、"011"
、"101"
、"110"
和 "111"
。
示例 2:
输入: n = 1
输出: ["0","1"]
解释:
长度为 1 的有效字符串有:"0"
和 "1"
。
提示:
1 <= n <= 18
class Solution {
public:
vector<string> validStrings(int n) {
if(n==1)return vector<string>{"0","1"};
auto v=validStrings(n-1);
vector<string> ans;
for(auto s:v){
if(s[n-2]=='1')ans.push_back(s+"0");
ans.push_back(s+"1");
}
return ans;
}
};
3216. 交换后字典序最小的字符串
给你一个仅由数字组成的字符串 s
,在最多交换一次 相邻 且具有相同 奇偶性 的数字后,返回可以得到的
字典序最小的字符串
。
如果两个数字都是奇数或都是偶数,则它们具有相同的奇偶性。例如,5 和 9、2 和 4 奇偶性相同,而 6 和 9 奇偶性不同。
示例 1:
输入: s = "45320"
输出: "43520"
解释:
s[1] == '5'
和 s[2] == '3'
都具有相同的奇偶性,交换它们可以得到字典序最小的字符串。
示例 2:
输入: s = "001"
输出: "001"
解释:
无需进行交换,因为 s
已经是字典序最小的。
提示:
2 <= s.length <= 100
s
仅由数字组成。
class Solution {
public:
string getSmallestString(string s) {
for(int i=0;i<s.length()-1;i++){
if((s[i]-s[i+1])%2==0 && s[i]>s[i+1]){
char c=s[i];
s[i]=s[i+1],s[i+1]=c;
return s;
}
}
return s;
}
};
3217. 从链表中移除在数组中存在的节点
给你一个整数数组 nums
和一个链表的头节点 head
。从链表中移除所有存在于 nums
中的节点后,返回修改后的链表的头节点。
示例 1:
输入: nums = [1,2,3], head = [1,2,3,4,5]
输出: [4,5]
解释:
移除数值为 1, 2 和 3 的节点。
示例 2:
输入: nums = [1], head = [1,2,1,2,1,2]
输出: [2,2,2]
解释:
移除数值为 1 的节点。
示例 3:
输入: nums = [5], head = [1,2,3,4]
输出: [1,2,3,4]
解释:
链表中不存在值为 5 的节点。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 105
nums
中的所有元素都是唯一的。- 链表中的节点数在
[1, 105]
的范围内。 1 <= Node.val <= 105
- 输入保证链表中至少有一个值没有在
nums
中出现过。
class Solution {
public:
ListNode* modifiedList(vector<int>& nums, ListNode* head) {
auto v=ListToVec(head);
map<int,int>m;
for(auto x:nums)m[x]++;
vector<ListNode*>v2;
for(auto x:v)if(m[x->val]==0)v2.push_back(x);
return VecToList(v2);
}
};
3218. 切蛋糕的最小总开销 I
3219. 切蛋糕的最小总开销 II的简化版
3219. 切蛋糕的最小总开销 II
3222. 求出硬币游戏的赢家
给你两个 正 整数 x
和 y
,分别表示价值为 75 和 10 的硬币的数目。
Alice 和 Bob 正在玩一个游戏。每一轮中,Alice 先进行操作,Bob 后操作。每次操作中,玩家需要拿走价值 总和 为 115 的硬币。如果一名玩家无法执行此操作,那么这名玩家 输掉 游戏。
两名玩家都采取 最优 策略,请你返回游戏的赢家。
示例 1:
输入:x = 2, y = 7
输出:"Alice"
解释:
游戏一次操作后结束:
- Alice 拿走 1 枚价值为 75 的硬币和 4 枚价值为 10 的硬币。
示例 2:
输入:x = 4, y = 11
输出:"Bob"
解释:
游戏 2 次操作后结束:
- Alice 拿走 1 枚价值为 75 的硬币和 4 枚价值为 10 的硬币。
- Bob 拿走 1 枚价值为 75 的硬币和 4 枚价值为 10 的硬币。
提示:
1 <= x, y <= 100
class Solution {
public:
string losingPlayer(int x, int y) {
return min(x,y/4)%2?"Alice":"Bob";
}
};
3226. 使两个整数相等的位更改次数
给你两个正整数 n
和 k
。
你可以选择 n
的 二进制表示 中任意一个值为 1 的位,并将其改为 0。
返回使得 n
等于 k
所需要的更改次数。如果无法实现,返回 -1。
示例 1:
输入: n = 13, k = 4
输出: 2
解释:
最初,n
和 k
的二进制表示分别为 n = (1101)2
和 k = (0100)2
,
我们可以改变 n
的第一位和第四位。结果整数为 n = (0100)2 = k
。
示例 2:
输入: n = 21, k = 21
输出: 0
解释:
n
和 k
已经相等,因此不需要更改。
示例 3:
输入: n = 14, k = 13
输出: -1
解释:
无法使 n
等于 k
。
提示:
1 <= n, k <= 106
class Solution {
public:
int minChanges(int n, int k) {
if((n&k)!=k)return -1;
n^=k;
int ans=0;
while(n){
n^=(n&-n);
ans++;
}
return ans;
}
};
3232. 判断是否可以赢得数字游戏
给你一个 正整数 数组 nums
。
Alice 和 Bob 正在玩游戏。在游戏中,Alice 可以从 nums
中选择所有个位数 或 所有两位数,剩余的数字归 Bob 所有。如果 Alice 所选数字之和 严格大于 Bob 的数字之和,则 Alice 获胜。
如果 Alice 能赢得这场游戏,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [1,2,3,4,10]
输出:false
解释:
Alice 不管选个位数还是两位数都无法赢得比赛。
示例 2:
输入:nums = [1,2,3,4,5,14]
输出:true
解释:
Alice 选择个位数可以赢得比赛,所选数字之和为 15。
示例 3:
输入:nums = [5,5,5,25]
输出:true
解释:
Alice 选择两位数可以赢得比赛,所选数字之和为 25。
提示:
1 <= nums.length <= 100
1 <= nums[i] <= 99
class Solution {
public:
bool canAliceWin(vector<int>& nums) {
int s1 = 0, s2 = 0;
for (auto x : nums) {
if (x < 10)s1 += x;
else s2 += x;
}
return s1 != s2;
}
};
3238. 求出胜利玩家的数目
给你一个整数 n
,表示在一个游戏中的玩家数目。同时给你一个二维整数数组 pick
,其中 pick[i] = [xi, yi]
表示玩家 xi
获得了一个颜色为 yi
的球。
如果玩家 i
获得的球中任何一种颜色球的数目 严格大于 i
个,那么我们说玩家 i
是胜利玩家。换句话说:
- 如果玩家 0 获得了任何的球,那么玩家 0 是胜利玩家。
- 如果玩家 1 获得了至少 2 个相同颜色的球,那么玩家 1 是胜利玩家。
- ...
- 如果玩家
i
获得了至少i + 1
个相同颜色的球,那么玩家i
是胜利玩家。
请你返回游戏中 胜利玩家 的数目。
注意,可能有多个玩家是胜利玩家。
示例 1:
输入:n = 4, pick = [[0,0],[1,0],[1,0],[2,1],[2,1],[2,0]]
输出:2
解释:
玩家 0 和玩家 1 是胜利玩家,玩家 2 和玩家 3 不是胜利玩家。
示例 2:
输入:n = 5, pick = [[1,1],[1,2],[1,3],[1,4]]
输出:0
解释:
没有胜利玩家。
示例 3:
输入:n = 5, pick = [[1,1],[2,4],[2,4],[2,4]]
输出:1
解释:
玩家 2 是胜利玩家,因为玩家 2 获得了 3 个颜色为 4 的球。
提示:
2 <= n <= 10
1 <= pick.length <= 100
pick[i].length == 2
0 <= xi <= n - 1
0 <= yi <= 10
class Solution {
public:
int winningPlayerCount(int n, vector<vector<int>>& pick) {
vector<map<int, int>>vm(n);
for (auto v : pick)vm[v[0]][v[1]]++;
int ans = 0;
for (int i = 0; i < n; i++) {
for (auto mi : vm[i])if (mi.second > i) {
ans++;
break;
}
}
return ans;
}
};
3239. 最少翻转次数使二进制矩阵回文 I
给你一个 m x n
的二进制矩阵 grid
。
如果矩阵中一行或者一列从前往后与从后往前读是一样的,那么我们称这一行或者这一列是 回文 的。
你可以将 grid
中任意格子的值 翻转 ,也就是将格子里的值从 0
变成 1
,或者从 1
变成 0
。
请你返回 最少 翻转次数,使得矩阵 要么 所有行是 回文的 ,要么所有列是 回文的 。
示例 1:
输入:grid = [[1,0,0],[0,0,0],[0,0,1]]
输出:2
解释:
将高亮的格子翻转,得到所有行都是回文的。
示例 2:
输入:grid = [[0,1],[0,1],[0,0]]
输出:1
解释:
将高亮的格子翻转,得到所有列都是回文的。
示例 3:
输入:grid = [[1],[0]]
输出:0
解释:
所有行已经是回文的。
提示:
m == grid.length
n == grid[i].length
1 <= m * n <= 2 * 105
0 <= grid[i][j] <= 1
class Solution {
public:
int minFlips(vector<vector<int>>& grid) {
int ans1 = 0, ans2 = 0;
for (auto v : grid)ans1 += minFlips(v);
for (int i = 0; i < grid[0].size(); i++) {
vector<int>v;
for (int j = 0; j < grid.size(); j++)v.push_back(grid[j][i]);
ans2 += minFlips(v);
}
return min(ans1, ans2);
}
int minFlips(vector<int>&v)
{
int s = 0;
for (int i = 0, j = v.size() - 1; i < j; i++, j--) {
s += (v[i] + v[j]) % 2;
}
return s;
}
};
3240. 最少翻转次数使二进制矩阵回文 II
给你一个 m x n
的二进制矩阵 grid
。
如果矩阵中一行或者一列从前往后与从后往前读是一样的,那么我们称这一行或者这一列是 回文 的。
你可以将 grid
中任意格子的值 翻转 ,也就是将格子里的值从 0
变成 1
,或者从 1
变成 0
。
请你返回 最少 翻转次数,使得矩阵中 所有 行和列都是 回文的 ,且矩阵中 1
的数目可以被 4
整除 。
示例 1:
输入:grid = [[1,0,0],[0,1,0],[0,0,1]]
输出:3
解释:
示例 2:
输入:grid = [[0,1],[0,1],[0,0]]
输出:2
解释:
示例 3:
输入:grid = [[1],[1]]
输出:2
解释:
提示:
m == grid.length
n == grid[i].length
1 <= m * n <= 2 * 105
0 <= grid[i][j] <= 1
class Solution {
public:
int minFlips(vector<vector<int>>& grid) {
int ans = 0, r = grid.size(), c = grid[0].size();
for (int i = 0; i < r / 2; i++) {
for (int j = 0; j < c / 2; j++) {
int s = grid[i][j] + grid[i][c - 1 - j] + grid[r - 1 - i][j] + grid[r - 1 - i][c - 1 - j];
if (s == 1 || s == 3)ans++;
if (s == 2)ans += 2;
}
}
if (r % 2 == 1 && c % 2 == 1)ans += grid[r / 2][c / 2];
int n01 = 0, n11 = 0;
if (r % 2 == 1) {
for (int j = 0; j < c / 2; j++) {
n01 += (grid[r / 2][j] ^ grid[r / 2][c - 1 - j]);
n11 += grid[r / 2][j] * grid[r / 2][c - 1 - j];
}
}
if (c % 2 == 1) {
for (int i = 0; i < r / 2; i++) {
n01 += (grid[i][c / 2] ^ grid[r - 1 - i][c / 2]);
n11 += grid[i][c / 2] * grid[r - 1 - i][c / 2];
}
}
ans += n01 ? n01 : (n11 % 2 * 2);
return ans;
}
};
3242. 设计相邻元素求和服务
给你一个 n x n
的二维数组 grid
,它包含范围 [0, n2 - 1]
内的不重复元素。
实现 neighborSum
类:
neighborSum(int [][]grid)
初始化对象。int adjacentSum(int value)
返回在grid
中与value
相邻的元素之和,相邻指的是与value
在上、左、右或下的元素。int diagonalSum(int value)
返回在grid
中与value
对角线相邻的元素之和,对角线相邻指的是与value
在左上、右上、左下或右下的元素。
示例 1:
输入:
["neighborSum", "adjacentSum", "adjacentSum", "diagonalSum", "diagonalSum"]
[[[[0, 1, 2], [3, 4, 5], [6, 7, 8]]], [1], [4], [4], [8]]
输出: [null, 6, 16, 16, 4]
解释:
- 1 的相邻元素是 0、2 和 4。
- 4 的相邻元素是 1、3、5 和 7。
- 4 的对角线相邻元素是 0、2、6 和 8。
- 8 的对角线相邻元素是 4。
示例 2:
输入:
["neighborSum", "adjacentSum", "diagonalSum"]
[[[[1, 2, 0, 3], [4, 7, 15, 6], [8, 9, 10, 11], [12, 13, 14, 5]]], [15], [9]]
输出: [null, 23, 45]
解释:
- 15 的相邻元素是 0、10、7 和 6。
- 9 的对角线相邻元素是 4、12、14 和 15。
提示:
3 <= n == grid.length == grid[0].length <= 10
0 <= grid[i][j] <= n2 - 1
- 所有
grid[i][j]
值均不重复。 adjacentSum
和diagonalSum
中的value
均在范围[0, n2 - 1]
内。- 最多会调用
adjacentSum
和diagonalSum
总共2 * n2
次。
class NeighborSum {
public:
NeighborSum(vector<vector<int>>& grid) {
this->grid = grid;
}
int adjacentSum(int value) {
int i=0,j=0,flag=true;
for(i=0;flag && i<grid.size();i++){
for(j=0;j<grid[i].size();j++){
if(grid[i][j]==value){
flag=false;
break;
}
}
}
int ans=0;
if(--i)ans+=grid[i-1][j];
if(i<grid.size()-1)ans+=grid[i+1][j];
if(j)ans+=grid[i][j-1];
if(j<grid[i].size()-1)ans+=grid[i][j+1];
return ans;
}
int diagonalSum(int value) {
int i=0,j=0,flag=true;
for(i=0;flag && i<grid.size();i++){
for(j=0;j<grid[i].size();j++){
if(grid[i][j]==value){
flag=false;
break;
}
}
}
int ans=0;
if(--i>0&&j>0)ans+=grid[i-1][j-1];
if(i>0&&j<grid[i].size()-1)ans+=grid[i-1][j+1];
if(i<grid.size()-1&&j>0)ans+=grid[i+1][j-1];
if(i<grid.size()-1&&j<grid[i].size()-1)ans+=grid[i+1][j+1];
return ans;
}
vector<vector<int>> grid;
};
3248. 矩阵中的蛇
大小为 n x n
的矩阵 grid
中有一条蛇。蛇可以朝 四个可能的方向 移动。矩阵中的每个单元格都使用位置进行标识: grid[i][j] = (i * n) + j
。
蛇从单元格 0 开始,并遵循一系列命令移动。
给你一个整数 n
表示 grid
的大小,另给你一个字符串数组 commands
,其中包括 "UP"
、"RIGHT"
、"DOWN"
和 "LEFT"
。题目测评数据保证蛇在整个移动过程中将始终位于 grid
边界内。
返回执行 commands
后蛇所停留的最终单元格的位置。
示例 1:
输入:n = 2, commands = ["RIGHT","DOWN"]
输出:3
解释:
0 | 1 |
2 | 3 |
0 | 1 |
2 | 3 |
0 | 1 |
2 | 3 |
示例 2:
输入:n = 3, commands = ["DOWN","RIGHT","UP"]
输出:1
解释:
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
提示:
2 <= n <= 10
1 <= commands.length <= 100
commands
仅由"UP"
、"RIGHT"
、"DOWN"
和"LEFT"
组成。- 生成的测评数据确保蛇不会移动到矩阵的边界外。
class Solution {
public:
int finalPositionOfSnake(int n, vector<string>& commands) {
int x = 0, y = 0;
for (auto s : commands) {
if (s == "UP")x--;
if (s == "DOWN")x++;
if (s == "LEFT")y--;
if (s == "RIGHT")y++;
}
return x * n + y;
}
};
3249. 统计好节点的数目
3250. 单调数组对的数目 I
给你一个长度为 n
的 正 整数数组 nums
。
如果两个 非负 整数数组 (arr1, arr2)
满足以下条件,我们称它们是 单调 数组对:
- 两个数组的长度都是
n
。 arr1
是单调 非递减 的,换句话说arr1[0] <= arr1[1] <= ... <= arr1[n - 1]
。arr2
是单调 非递增 的,换句话说arr2[0] >= arr2[1] >= ... >= arr2[n - 1]
。- 对于所有的
0 <= i <= n - 1
都有arr1[i] + arr2[i] == nums[i]
。
请你返回所有 单调 数组对的数目。
由于答案可能很大,请你将它对 109 + 7
取余 后返回。
示例 1:
输入:nums = [2,3,2]
输出:4
解释:
单调数组对包括:
([0, 1, 1], [2, 2, 1])
([0, 1, 2], [2, 2, 0])
([0, 2, 2], [2, 1, 0])
([1, 2, 2], [1, 1, 0])
示例 2:
输入:nums = [5,5,5,5]
输出:126
提示:
1 <= n == nums.length <= 2000
1 <= nums[i] <= 50
本题同3251. 单调数组对的数目 II,只是数据量小一点。
3251. 单调数组对的数目 II
给你一个长度为 n
的 正 整数数组 nums
。
如果两个 非负 整数数组 (arr1, arr2)
满足以下条件,我们称它们是 单调 数组对:
- 两个数组的长度都是
n
。 arr1
是单调 非递减 的,换句话说arr1[0] <= arr1[1] <= ... <= arr1[n - 1]
。arr2
是单调 非递增 的,换句话说arr2[0] >= arr2[1] >= ... >= arr2[n - 1]
。- 对于所有的
0 <= i <= n - 1
都有arr1[i] + arr2[i] == nums[i]
。
请你返回所有 单调 数组对的数目。
由于答案可能很大,请你将它对 109 + 7
取余 后返回。
示例 1:
输入:nums = [2,3,2]
输出:4
解释:
单调数组对包括:
([0, 1, 1], [2, 2, 1])
([0, 1, 2], [2, 2, 0])
([0, 2, 2], [2, 1, 0])
([1, 2, 2], [1, 1, 0])
示例 2:
输入:nums = [5,5,5,5]
输出:126
提示:
1 <= n == nums.length <= 2000
1 <= nums[i] <= 1000
class Solution {
public:
int countOfPairs(vector<int>& nums) {
int p = 1000000007;
vector<long long>ans(1001, 0);
for (int i = 0; i <= nums[0]; i++)ans[i] = 1;
for (int i = 1; i < nums.size(); i++) {
for (int i = 1; i <= 1000; i++)ans[i] = (ans[i] + ans[i - 1]) % p;
vector<long long>s(1001, 0);
for (int j = 0; j <= nums[i]; j++) {
auto maxid = min(nums[i - 1], min(j, j + nums[i - 1] - nums[i]));
if (maxid >= 0)s[j] = ans[maxid];
}
ans = s;
}
long long r = 0;
for (int i = 0; i <= 1000; i++)r = (r + ans[i]) % p;
return r % p;
}
};
3254. 长度为 K 的子数组的能量值 I
给你一个长度为 n
的整数数组 nums
和一个正整数 k
。
一个数组的 能量值 定义为:
- 如果 所有 元素都是依次 连续 且 上升 的,那么能量值为 最大 的元素。
- 否则为 -1 。
你需要求出 nums
中所有长度为 k
的
子数组
的能量值。
请你返回一个长度为 n - k + 1
的整数数组 results
,其中 results[i]
是子数组 nums[i..(i + k - 1)]
的能量值。
示例 1:
输入:nums = [1,2,3,4,3,2,5], k = 3
输出:[3,4,-1,-1,-1]
解释:
nums
中总共有 5 个长度为 3 的子数组:
[1, 2, 3]
中最大元素为 3 。[2, 3, 4]
中最大元素为 4 。[3, 4, 3]
中元素 不是 连续的。[4, 3, 2]
中元素 不是 上升的。[3, 2, 5]
中元素 不是 连续的。
示例 2:
输入:nums = [2,2,2,2,2], k = 4
输出:[-1,-1]
示例 3:
输入:nums = [3,2,3,2,3,2], k = 2
输出:[-1,3,-1,3,-1]
提示:
1 <= n == nums.length <= 500
1 <= nums[i] <= 105
1 <= k <= n
class Solution {
public:
vector<int> resultsArray(vector<int>& nums, int k) {
int n = 0;
for (int i = 1; i < k; i++)if (nums[i] - nums[i - 1] == 1)n++;
vector<int>ans;
ans.push_back((n == k - 1) ? nums[k - 1] : -1);
for (int i = k; i < nums.size(); i++) {
if (nums[i] - nums[i - 1] == 1)n++;
if (nums[i - k + 1] - nums[i - k] == 1)n--;
ans.push_back((n == k - 1) ? nums[i] : -1);
}
return ans;
}
};
3255. 长度为 K 的子数组的能量值 II
给你一个长度为 n
的整数数组 nums
和一个正整数 k
。
一个数组的 能量值 定义为:
- 如果 所有 元素都是依次 连续(即
nums[i] + 1 = nums[i + 1]
,i < n
)且 上升 的,那么能量值为 最大 的元素。 - 否则为 -1 。
你需要求出 nums
中所有长度为 k
的
子数组
的能量值。
请你返回一个长度为 n - k + 1
的整数数组 results
,其中 results[i]
是子数组 nums[i..(i + k - 1)]
的能量值。
示例 1:
输入:nums = [1,2,3,4,3,2,5], k = 3
输出:[3,4,-1,-1,-1]
解释:
nums
中总共有 5 个长度为 3 的子数组:
[1, 2, 3]
中最大元素为 3 。[2, 3, 4]
中最大元素为 4 。[3, 4, 3]
中元素 不是 连续的。[4, 3, 2]
中元素 不是 上升的。[3, 2, 5]
中元素 不是 连续的。
示例 2:
输入:nums = [2,2,2,2,2], k = 4
输出:[-1,-1]
示例 3:
输入:nums = [3,2,3,2,3,2], k = 2
输出:[-1,3,-1,3,-1]
提示:
1 <= n == nums.length <= 105
1 <= nums[i] <= 106
1 <= k <= n
class Solution {
public:
vector<int> resultsArray(vector<int>& nums, int k) {
int n = 0;
for (int i = 1; i < k; i++)if (nums[i] - nums[i - 1] == 1)n++;
vector<int>ans;
ans.push_back((n == k - 1) ? nums[k - 1] : -1);
for (int i = k; i < nums.size(); i++) {
if (nums[i] - nums[i - 1] == 1)n++;
if (nums[i - k + 1] - nums[i - k] == 1)n--;
ans.push_back((n == k - 1) ? nums[i] : -1);
}
return ans;
}
};
3258. 统计满足 K 约束的子字符串数量 I
给你一个 二进制 字符串 s
和一个整数 k
。
如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束:
- 字符串中
0
的数量最多为k
。 - 字符串中
1
的数量最多为k
。
返回一个整数,表示 s
的所有满足 k 约束 的
子字符串
的数量。
示例 1:
输入:s = "10101", k = 1
输出:12
解释:
s
的所有子字符串中,除了 "1010"
、"10101"
和 "0101"
外,其余子字符串都满足 k 约束。
示例 2:
输入:s = "1010101", k = 2
输出:25
解释:
s
的所有子字符串中,除了长度大于 5 的子字符串外,其余子字符串都满足 k 约束。
示例 3:
输入:s = "11111", k = 1
输出:15
解释:
s
的所有子字符串都满足 k 约束。
提示:
1 <= s.length <= 50
1 <= k <= s.length
s[i]
是'0'
或'1'
。
class Solution {
public:
int countKConstraintSubstrings(string s, int k) {
vector<vector<int>>ids(2);
int ans = 0;
for (int i = 0; i < s.length(); i++) {
auto &v = ids[s[i] - '0'];
auto &v2 = ids[1-(s[i] - '0')];
v.push_back(i);
int id1 = ((v.size() > k) ? v[v.size() - 1 - k] : -1);
int id2 = ((v2.size() > k) ? v2[v2.size() - 1 - k] : -1);
ans += i - min(id1, id2);
}
return ans;
}
};
3259. 超级饮料的最大强化能量
来自未来的体育科学家给你两个整数数组 energyDrinkA
和 energyDrinkB
,数组长度都等于 n
。这两个数组分别代表 A、B 两种不同能量饮料每小时所能提供的强化能量。
你需要每小时饮用一种能量饮料来 最大化 你的总强化能量。然而,如果从一种能量饮料切换到另一种,你需要等待一小时来梳理身体的能量体系(在那个小时里你将不会获得任何强化能量)。
返回在接下来的 n
小时内你能获得的 最大 总强化能量。
注意 你可以选择从饮用任意一种能量饮料开始。
示例 1:
输入:energyDrinkA = [1,3,1], energyDrinkB = [3,1,1]
输出:5
解释:
要想获得 5 点强化能量,需要选择只饮用能量饮料 A(或者只饮用 B)。
示例 2:
输入:energyDrinkA = [4,1,1], energyDrinkB = [1,1,3]
输出:7
解释:
- 第一个小时饮用能量饮料 A。
- 切换到能量饮料 B ,在第二个小时无法获得强化能量。
- 第三个小时饮用能量饮料 B ,并获得强化能量。
提示:
n == energyDrinkA.length == energyDrinkB.length
3 <= n <= 105
1 <= energyDrinkA[i], energyDrinkB[i] <= 105
class Solution {
public:
long long maxEnergyBoost(vector<int>& A, vector<int>& B) {
long long a0 = A[0], b0 = B[0];
if (A.size() == 1)return max(a0, b0);
long long a1 = a0 + A[1], b1 = b0 + B[1];
for (int i = 2; i < A.size(); i++) {
long long a2 = max(a1, b0) + A[i],b2 = max(b1, a0) + B[i];
a0 = a1, a1 = a2, b0 = b1, b1 = b2;
}
return max(a1, b1);
}
};
3261. 统计满足 K 约束的子字符串数量 II
给你一个 二进制 字符串 s
和一个整数 k
。
另给你一个二维整数数组 queries
,其中 queries[i] = [li, ri]
。
如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束:
- 字符串中
0
的数量最多为k
。 - 字符串中
1
的数量最多为k
。
返回一个整数数组 answer
,其中 answer[i]
表示 s[li..ri]
中满足 k 约束 的
子字符串
的数量。
示例 1:
输入:s = "0001111", k = 2, queries = [[0,6]]
输出:[26]
解释:
对于查询 [0, 6]
, s[0..6] = "0001111"
的所有子字符串中,除 s[0..5] = "000111"
和 s[0..6] = "0001111"
外,其余子字符串都满足 k 约束。
示例 2:
输入:s = "010101", k = 1, queries = [[0,5],[1,4],[2,3]]
输出:[15,9,3]
解释:
s
的所有子字符串中,长度大于 3 的子字符串都不满足 k 约束。
提示:
1 <= s.length <= 105
s[i]
是'0'
或'1'
1 <= k <= s.length
1 <= queries.length <= 105
queries[i] == [li, ri]
0 <= li <= ri < s.length
- 所有查询互不相同
class Solution {
public:
vector<long long> countKConstraintSubstrings(string s, int k, vector<vector<int>>& queries) {
vector<vector<int>>ids(2);
vector<int>startId;
for (int i = 0; i < s.length(); i++) {
auto &v = ids[s[i] - '0'];
auto &v2 = ids[1 - (s[i] - '0')];
v.push_back(i);
int id1 = ((v.size() > k) ? v[v.size() - 1 - k] : -1);
int id2 = ((v2.size() > k) ? v2[v2.size() - 1 - k] : -1);
startId.push_back(min(id1, id2));
}
map<int, int>m;//反射,m[i]是满足startId[x]>=i的最小x
for (int i = 0; i < startId.size(); i++) {
if (m.find(startId[i]) == m.end())m[startId[i]] = i;
}
m[s.length()] = s.length();
for (int i = s.length() - 1; i >= 0; i--) {
if (m.find(i) == m.end())m[i] = m[i + 1];
}
map<int, long long>preSum;
long long ps = 0;
for (int i = 0; i < s.length(); i++) {
ps += i - startId[i];
preSum[i]=ps;
}
vector<long long> ans;
for (auto q : queries) {
long long s = 0;
int id = m[q[0]];
if (id > q[1]) {
s = ((long long)(q[1] - q[0] + 1))*(q[1] - q[0] + 2) / 2;
}
else {
s = ((long long)(id - q[0]))*(id - q[0] + 1) / 2;
s += preSum[q[1]] - preSum[id - 1];
}
ans.push_back(s);
}
return ans;
}
};
3264. K 次乘运算后的最终数组 I
K 次乘运算后的最终数组 II的简化版
3266. K 次乘运算后的最终数组 II
给你一个整数数组 nums
,一个整数 k
和一个整数 multiplier
。
你需要对 nums
执行 k
次操作,每次操作中:
- 找到
nums
中的 最小 值x
,如果存在多个最小值,选择最 前面 的一个。 - 将
x
替换为x * multiplier
。
k
次操作以后,你需要将 nums
中每一个数值对 109 + 7
取余。
请你返回执行完 k
次乘运算以及取余运算之后,最终的 nums
数组。
示例 1:
输入:nums = [2,1,3,5,6], k = 5, multiplier = 2
输出:[8,4,6,5,6]
解释:
操作 | 结果 |
---|---|
1 次操作后 | [2, 2, 3, 5, 6] |
2 次操作后 | [4, 2, 3, 5, 6] |
3 次操作后 | [4, 4, 3, 5, 6] |
4 次操作后 | [4, 4, 6, 5, 6] |
5 次操作后 | [8, 4, 6, 5, 6] |
取余操作后 | [8, 4, 6, 5, 6] |
示例 2:
输入:nums = [100000,2000], k = 2, multiplier = 1000000
输出:[999999307,999999993]
解释:
操作 | 结果 |
---|---|
1 次操作后 | [100000, 2000000000] |
2 次操作后 | [100000000000, 2000000000] |
取余操作后 | [999999307, 999999993] |
提示:
1 <= nums.length <= 104
1 <= nums[i] <= 109
1 <= k <= 109
1 <= multiplier <= 106
class Solution{
public:
vector<int> getFinalState(vector<int>& nums, int k, int multiplier) {
if (multiplier <= 1)return nums;
priority_queue<Node, vector<Node>, greater<Node>>q;
long long maxVal = 0;
Node nod;
for (nod.id = 0; nod.id < nums.size(); nod.id++) {
nod.val = nums[nod.id];
maxVal = max(maxVal, nod.val);
q.push(nod);
}
bool flag = false;
while (true) {
Node nod = q.top();
if (nod.val * multiplier > maxVal)flag = true;
if (flag && k%nums.size() == 0) {
break;
}
q.pop();
nod.val = nod.val * multiplier;
maxVal = max(maxVal, nod.val);
nums[nod.id] = nod.val % 1000000007;
q.push(nod);
if (--k== 0)break;
}
if (k) {
long long m = MultiMulti(multiplier, k / nums.size(), 1000000007);
for (auto &x : nums)x = x * m % 1000000007;
}
return nums;
}
};
3270. 求出数字答案
给你三个 正 整数 num1
,num2
和 num3
。
数字 num1
,num2
和 num3
的数字答案 key
是一个四位数,定义如下:
- 一开始,如果有数字 少于 四位数,给它补 前导 0 。
- 答案
key
的第i
个数位(1 <= i <= 4
)为num1
,num2
和num3
第i
个数位中的 最小 值。
请你返回三个数字 没有 前导 0 的数字答案。
示例 1:
输入:num1 = 1, num2 = 10, num3 = 1000
输出:0
解释:
补前导 0 后,num1
变为 "0001"
,num2
变为 "0010"
,num3
保持不变,为 "1000"
。
- 数字答案
key
的第1
个数位为min(0, 0, 1)
。 - 数字答案
key
的第2
个数位为min(0, 0, 0)
。 - 数字答案
key
的第3
个数位为min(0, 1, 0)
。 - 数字答案
key
的第4
个数位为min(1, 0, 0)
。
所以数字答案为 "0000"
,也就是 0 。
示例 2:
输入: num1 = 987, num2 = 879, num3 = 798
输出:777
示例 3:
输入:num1 = 1, num2 = 2, num3 = 3
输出:1
提示:
1 <= num1, num2, num3 <= 9999
class Solution {
public:
int generateKey(int num1, int num2, int num3) {
int ans = min(num1 % 10, min(num2 % 10, num3 % 10));
num1 /= 10, num2 /= 10, num3 /= 10;
ans += min(num1 % 10, min(num2 % 10, num3 % 10)) * 10;
num1 /= 10, num2 /= 10, num3 /= 10;
ans += min(num1 % 10, min(num2 % 10, num3 % 10)) * 100;
ans += min(num1 / 10, min(num2 / 10, num3 / 10)) * 1000;
return ans;
}
};
3274. 检查棋盘方格颜色是否相同
给你两个字符串 coordinate1
和 coordinate2
,代表 8 x 8
国际象棋棋盘上的两个方格的坐标。
以下是棋盘的参考图。
如果这两个方格颜色相同,返回 true
,否则返回 false
。
坐标总是表示有效的棋盘方格。坐标的格式总是先字母(表示列),再数字(表示行)。
示例 1:
输入: coordinate1 = "a1", coordinate2 = "c3"
输出: true
解释:
两个方格均为黑色。
示例 2:
输入: coordinate1 = "a1", coordinate2 = "h3"
输出: false
解释:
方格 "a1"
是黑色,而 "h3"
是白色。
提示:
coordinate1.length == coordinate2.length == 2
'a' <= coordinate1[0], coordinate2[0] <= 'h'
'1' <= coordinate1[1], coordinate2[1] <= '8'
class Solution {
public:
bool checkTwoChessboards(string s1, string s2) {
return !((s1[0]+s1[1]+s2[0]+s2[1])&1);
}
};
3285. 找到稳定山的下标
有 n
座山排成一列,每座山都有一个高度。给你一个整数数组 height
,其中 height[i]
表示第 i
座山的高度,再给你一个整数 threshold
。
对于下标不为 0
的一座山,如果它左侧相邻的山的高度 严格大于 threshold
,那么我们称它是 稳定 的。我们定义下标为 0
的山 不是 稳定的。
请你返回一个数组,包含所有 稳定 山的下标,你可以以 任意 顺序返回下标数组。
示例 1:
输入:height = [1,2,3,4,5], threshold = 2
输出:[3,4]
解释:
- 下标为 3 的山是稳定的,因为
height[2] == 3
大于threshold == 2
。 - 下标为 4 的山是稳定的,因为
height[3] == 4
大于threshold == 2
.
示例 2:
输入:height = [10,1,10,1,10], threshold = 3
输出:[1,3]
示例 3:
输入:height = [10,1,10,1,10], threshold = 10
输出:[]
提示:
2 <= n == height.length <= 100
1 <= height[i] <= 100
1 <= threshold <= 100
class Solution {
public:
vector<int> stableMountains(vector<int>& height, int threshold) {
vector<int>ans;
for(int i=0;i<height.size()-1;i++){
if(height[i]>threshold)ans.push_back(i+1);
}
return ans;
}
};