题目:
今天的题目使用的是两个哈希表对照的解法。
我们的思路是这样:
1.对于一个序列,我们只考虑它的结尾数字。即,以这个数字为结尾的序列有多少个。
2.对于一个数字X,我们考虑它X-1是否为一个序列的结尾
如果是,则将该数字加入这个序列。然后修改该序列的结尾为X,以X-1为序列的个数减少一,同理,以结尾为X的个数增加一
如果不是,则判断X+1与X+2是否还有数字剩余,如果有,则加入,构成一个新序列。X,X+1,X+2的数字个数减少一,以X+2为结尾的序列个数增加1
否则,则无法构成新序列,返回False,其余情况返回True
我们首先统计每一个数字出现的次数,然后对nums中的每一个数字做判断即可。
C++代码加测试如下:
#include<iostream>
#include<vector>
#include<unordered_map>
#include<queue>
using namespace std;
class Solution {
public:
bool isPossible(vector<int>& nums) {
unordered_map<int, int> countMap;//剩余数字的计数哈希表
unordered_map<int, int> endMap;//队尾数字的计数哈希表
for (auto& x : nums) {
int count = countMap[x] + 1;
countMap[x] = count;//统计对应数字数量
}
for (auto& x : nums) {//对剩余数字计数表每个数字做判断
int count = countMap[x];//剩余数量
if (count > 0) {//如果当前剩余数量大于0
int prevEndCount = endMap[x - 1];//记录以x-1为结尾的序列数个数
if (prevEndCount > 0) {//如果存在以x-1为结尾的序列数个数
countMap[x] = count - 1;//将x加入该序列,剩余个数减一
endMap[x - 1] = prevEndCount - 1;//以x-1为结尾的序列个数减一
endMap[x] = endMap[x] + 1;//以x为结尾的个数加一
}
else {//如果不存在以x-1为结尾的序列
int count1 = countMap[x + 1];//检查x+1与x+2的数量
int count2 = countMap[x + 2];
if (count1 > 0 && count2 > 0) {//如果x+1与x+2的数量均大于0,即能构成最小序列
countMap[x] = count - 1;//当前数字数量-1
countMap[x + 1] = count1 - 1;//x+1与x+2数字的数量-1
countMap[x + 2] = count2 - 1;
endMap[x + 2] = endMap[x + 2] + 1;//以x+2为结尾的序列数量+1
}
else {//如果上述条件都不满足,则说明无法构成序列
return false;
}
}
}
}
return true; //若每个数字都不返回false,则说明可以构成序列
}
};
int main()
{
vector<int> nums = {1,2,3,3,4,5};
Solution s;
cout<<s.isPossible(nums)<<endl;
}
此外,评论区有一个队列的方法写的很好,空间复杂度和时间复杂度都为O(n),我虽然弄懂了大致算法,但是我C++代码功底不够好,没能实现出来。以后如果遇到类似的题目,我会尝试写写。