2347. 最好的扑克手牌 - 力扣(LeetCode)
给你一个整数数组 ranks
和一个字符数组 suit
。你有 5
张扑克牌,第 i
张牌大小为 ranks[i]
,花色为 suits[i]
。
下述是从好到坏你可能持有的 手牌类型 :
"Flush"
:同花,五张相同花色的扑克牌。"Three of a Kind"
:三条,有 3 张大小相同的扑克牌。"Pair"
:对子,两张大小一样的扑克牌。"High Card"
:高牌,五张大小互不相同的扑克牌。
请你返回一个字符串,表示给定的 5 张牌中,你能组成的 最好手牌类型 。
**注意:**返回的字符串 大小写 需与题目描述相同。
示例 1:
输入:ranks = [13,2,3,1,9], suits = ["a","a","a","a","a"]
输出:"Flush"
解释:5 张扑克牌的花色相同,所以返回 "Flush" 。
示例 2:
输入:ranks = [4,4,2,4,4], suits = ["d","a","a","b","c"]
输出:"Three of a Kind"
解释:第一、二和四张牌组成三张相同大小的扑克牌,所以得到 "Three of a Kind" 。
注意我们也可以得到 "Pair" ,但是 "Three of a Kind" 是更好的手牌类型。
有其他的 3 张牌也可以组成 "Three of a Kind" 手牌类型。
示例 3:
输入:ranks = [10,10,2,12,9], suits = ["a","b","c","a","d"]
输出:"Pair"
解释:第一和第二张牌大小相同,所以得到 "Pair" 。
我们无法得到 "Flush" 或者 "Three of a Kind" 。
提示:
ranks.length == suits.length == 5
1 <= ranks[i] <= 13
'a' <= suits[i] <= 'd'
- 任意两张扑克牌不会同时有相同的大小和花色。
思路:
我们直接按照优先级考虑即可
class Solution {
public:
string bestHand(vector<int>& ranks, vector<char>& suits) {
set<char> s(suits.begin(), suits.end());
if(s.size() == 1)
return "Flush";
int cnt[14] = {0};
for(auto c : ranks)
cnt[c] ++;
for(int i = 0; i < 14; i ++)
if(cnt[i] >= 3)
return "Three of a Kind";
for(int i = 0; i < 14; i ++)
if(cnt[i] == 2)
return "Pair";
return "High Card";
}
};
2348. 全 0 子数组的数目 - 力扣(LeetCode)
给你一个整数数组 nums
,返回全部为 0
的 子数组 数目。
子数组 是一个数组中一段连续非空元素组成的序列。
示例 1:
输入:nums = [1,3,0,0,2,0,0,4]
输出:6
解释:
子数组 [0] 出现了 4 次。
子数组 [0,0] 出现了 2 次。
不存在长度大于 2 的全 0 子数组,所以我们返回 6 。
示例 2:
输入:nums = [0,0,0,2,0,0]
输出:9
解释:
子数组 [0] 出现了 5 次。
子数组 [0,0] 出现了 3 次。
子数组 [0,0,0] 出现了 1 次。
不存在长度大于 3 的全 0 子数组,所以我们返回 9 。
示例 3:
输入:nums = [2,10,2019]
输出:0
解释:没有全 0 子数组,所以我们返回 0 。
提示:
1 <= nums.length <= 105
-109 <= nums[i] <= 109
思路:
我们注意到,对于一个连续 0 0 0的字符串,每次增加 1 1 1个,就可以和前面的 c n t cnt cnt个 0 0 0组合,给答案贡献 c n t + 1 cnt + 1 cnt+1个,所以我们只需要统计0的个数即可
举个例子 00 − > 000 00->000 00−>000 ,增加的一个 0 0 0,可以增加3个答案,第一个是单独的 0 0 0,第二个是和前面1个组成的00,第三个是和前面两个组成的000
class Solution {
public:
long long zeroFilledSubarray(vector<int>& nums) {
long long ans = 0L;
int c = 0;
for(auto& x : nums)
{
if(x) c = 0;
else ans += ++ c;
}
return ans;
}
};
2349. 设计数字容器系统 - 力扣(LeetCode)
设计一个数字容器系统,可以实现以下功能:
- 在系统中给定下标处 插入 或者 替换 一个数字。
- 返回 系统中给定数字的最小下标。
请你实现一个 NumberContainers
类:
NumberContainers()
初始化数字容器系统。void change(int index, int number)
在下标index
处填入number
。如果该下标index
处已经有数字了,那么用number
替换该数字。int find(int number)
返回给定数字number
在系统中的最小下标。如果系统中没有number
,那么返回-1
。
示例:
输入:
["NumberContainers", "find", "change", "change", "change", "change", "find", "change", "find"]
[[], [10], [2, 10], [1, 10], [3, 10], [5, 10], [10], [1, 20], [10]]
输出:
[null, -1, null, null, null, null, 1, null, 2]
解释:
NumberContainers nc = new NumberContainers();
nc.find(10); // 没有数字 10 ,所以返回 -1 。
nc.change(2, 10); // 容器中下标为 2 处填入数字 10 。
nc.change(1, 10); // 容器中下标为 1 处填入数字 10 。
nc.change(3, 10); // 容器中下标为 3 处填入数字 10 。
nc.change(5, 10); // 容器中下标为 5 处填入数字 10 。
nc.find(10); // 数字 10 所在的下标为 1 ,2 ,3 和 5 。因为最小下标为 1 ,所以返回 1 。
nc.change(1, 20); // 容器中下标为 1 处填入数字 20 。注意,下标 1 处之前为 10 ,现在被替换为 20 。
nc.find(10); // 数字 10 所在下标为 2 ,3 和 5 。最小下标为 2 ,所以返回 2 。
提示:
1 <= index, number <= 109
- 调用
change
和find
的 总次数 不超过105
次。
思路:
我们用一个map<int, int>mp
来维护当前这个mp[i]
表示下标 i
现在是什么数字,再维护 map<int, set<int>> nums
,nums[i]
表示数字 i
的所有下标。因为 set<int>
是有序的,所以最小的下标就是 set 里的第一个元素。每次操作复杂度都是
O
(
l
o
g
n
)
O(logn)
O(logn)的。
class NumberContainers {
public:
map<int, set<int>> nums;
map<int, int> mp;
NumberContainers() {
}
void change(int index, int number) {
if(mp.count(index))
{
int old = mp[index];
nums[old].erase(index);
}
mp[index] = number;
nums[number].insert(index);
}
int find(int number) {
set<int> &st = nums[number];
if(st.size() == 0) return -1;
return *(st.begin());
}
};
/**
* Your NumberContainers object will be instantiated and called as such:
* NumberContainers* obj = new NumberContainers();
* obj->change(index,number);
* int param_2 = obj->find(number);
*/
2350. 不可能得到的最短骰子序列 - 力扣(LeetCode)
给你一个长度为 n
的整数数组 rolls
和一个整数 k
。你扔一个 k
面的骰子 n
次,骰子的每个面分别是 1
到 k
,其中第 i
次扔得到的数字是 rolls[i]
。
请你返回 无法 从 rolls
中得到的 最短 骰子子序列的长度。
扔一个 k
面的骰子 len
次得到的是一个长度为 len
的 骰子子序列 。
注意 ,子序列只需要保持在原数组中的顺序,不需要连续。
示例 1:
输入:rolls = [4,2,1,2,3,3,2,4,1], k = 4
输出:3
解释:所有长度为 1 的骰子子序列 [1] ,[2] ,[3] ,[4] 都可以从原数组中得到。
所有长度为 2 的骰子子序列 [1, 1] ,[1, 2] ,... ,[4, 4] 都可以从原数组中得到。
子序列 [1, 4, 2] 无法从原数组中得到,所以我们返回 3 。
还有别的子序列也无法从原数组中得到。
示例 2:
输入:rolls = [1,1,2,2], k = 2
输出:2
解释:所有长度为 1 的子序列 [1] ,[2] 都可以从原数组中得到。
子序列 [2, 1] 无法从原数组中得到,所以我们返回 2 。
还有别的子序列也无法从原数组中得到,但 [2, 1] 是最短的子序列。
示例 3:
输入:rolls = [1,1,3,2,2,2,3,3], k = 4
输出:1
解释:子序列 [4] 无法从原数组中得到,所以我们返回 1 。
还有别的子序列也无法从原数组中得到,但 [4] 是最短的子序列。
提示:
n == rolls.length
1 <= n <= 105
1 <= rolls[i] <= k <= 105
思路:
这道题是贪心思路,我们考虑每次枚举一段包含有 1 到 k 1到 k 1到k,第子段,可以证明这段中含有所有的长度为1的字段,接下来我们维护第二段包含有1到k的字段,可以证明长度为2的所有字段均包含有,所以递推值第cnt段,余下的段不足1到k,我们可以证明最多可以获取的段就是cnt ,答案即为cnt+ 1
class Solution {
public:
int shortestSequence(vector<int>& rolls, int k) {
int n = rolls.size();
unordered_set<int> hash;
int cnt = 0;
for(int i = 0; i < n; i ++)
{
int j = i;
while(j < n && hash.size() < k) hash.insert(rolls[j ++]);
if(hash.size() == k)
{
hash.clear();
cnt ++;
}
i = j - 1;
}
return cnt + 1;
}
};