1. 题目

给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个子序列,其中每个子序列都由连续整数组成且长度至少为 3 。

如果可以完成上述分割,则返回 true ;否则,返回 false 。

示例 1: 输入: [1,2,3,3,4,5] 输出: True 解释: 你可以分割出这样两个连续子序列 : 1, 2, 3 3, 4, 5

示例 2: 输入: [1,2,3,3,4,4,5,5] 输出: True 解释: 你可以分割出这样两个连续子序列 : 1, 2, 3, 4, 5 3, 4, 5

示例 3: 输入: [1,2,3,4,4,5] 输出: False

提示: 输入的数组长度范围为 [1, 10000]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/split-array-into-consecutive-subsequences 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题思路

贪心。

当 x 在数组中时,如果存在一个子序列以 x-1 结尾,长度为 k,则可以将 x 加入该子序列中,得到长度为 k+1的子序列。如果不存在以 x-1结尾的子序列,则必须新建一个只包含 x 的子序列,长度为 1。

对于数组中的元素 x,如果存在一个子序列以 x-1 结尾,则可以将 x 加入该子序列中。将 x 加入已有的子序列总是比新建一个只包含 x 的子序列更优,因为前者可以将一个已有的子序列的长度增加 1,而后者新建一个长度为 1 的子序列,而题目要求分割成的子序列的长度都不小于 3,因此应该尽量避免新建短的子序列。

引入哈希表count、seq

count [i] = j 表示当前数字i在数组中还剩下j个没有放入满足要求的序列

seq [i] = j 表示长度为i的满足要求的序列已有j个

3. 代码

class Solution {
public:
    bool isPossible(vector<int>& nums) {
        unordered_map<int,int> count,seq;
        for(auto &x: nums) count[x]++;
        for(auto &x: nums){
            int cnt = count[x];
            if(!cnt)  continue;
            int preSeqCnt = seq[x-1]; 
            if(preSeqCnt){//存在一个子序列以 x-1 结尾,则将 x 加入该子序列中
                count[x]--;
                seq[x-1]--;
                seq[x]++;
            }else{//否则要新起一个子序列
                int sufNum1cnt = count[x+1];
                int sufNum2cnt = count[x+2];
                if(sufNum1cnt && sufNum2cnt){
                    count[x]--;
                    count[x+1]--;
                    count[x+2]--;
                    seq[x+2]++;
                }else return false;
            }
        }
        return true;
    }
};

results matching ""

    No results matching ""