[Leetcode] 659. Split Array into Consecutive Subsequences 解题报告

题目

You are given an integer array sorted in ascending order (may contain duplicates), you need to split them into several subsequences, where each subsequences consist of at least 3 consecutive integers. Return whether you can make such a split.

Example 1:

Input: [1,2,3,3,4,5]
Output: True
Explanation:
You can split them into two consecutive subsequences : 
1, 2, 3
3, 4, 5

Example 2:

Input: [1,2,3,3,4,4,5,5]
Output: True
Explanation:
You can split them into two consecutive subsequences : 
1, 2, 3, 4, 5
3, 4, 5

Example 3:

Input: [1,2,3,4,4,5]
Output: False

Note:

  1. The length of the input is in range of [1, 10000]

思路

感觉这道题目的难度直逼hard。我参考了网上的解法:

1)如果中间存在不连续的数字,则我们将它们分开,分别检查每个连续的序列,例如1,2,3,4,5,9,10,11。

2)计算每个数字出现的次数counts(每个数字的具体值其实并不重要)。

3)定义ones[i]表示长度为1的以第i个数字结尾的子串的个数;twos表示长度为2的以第i个数字为结尾的子串个数,tol表示所有以第i个数字作为结尾的子串个数。当处理下一个数字的时候,如果counts[i + 1] < ones + twos,那么说明没有办法进行合法的split了,所以返回false。否则我们就优先将当前的数字连接到相对短的子串上。所以:

twos[i + 1] = ones[i],ones[i +1] = counts[i + 1] - tot[i],而tot[i + 1] = counts[i + 1]。

最终整个子串能够被合法分解的充要条件是ones[n]和twos[n]都是0。看上面的递推公式可以发现,ones,twos和tot的第i + 1个值只与它们的第i和第i+1个值有关,所以该DP的空间复杂度可以进一步降低到O(1),请见下面的代码片段。

代码

class Solution {
public:
    bool isPossible(vector& nums) {
        int n = nums.size(), k = 0;
        for (int i = 1; i < n; i++) {
            if (nums[i] - nums[i - 1] > 1) {    // not continous, so check separately
                if (!check(nums, k, i)) {
                    return false;
                }
                k = i;
            }
        }
        return check(nums, k, n);
    }
private:
    bool check(vector& nums, int s, int e) {
        int ones = 0, twos = 0, tot = 0;
        for (int i = s + 1, cnt = 1; i <= e; i++) {
            if (i < e && nums[i] == nums[i-1]) {
                cnt++;
            }
            else {
                if (cnt < ones + twos) {
                    return false;
                }
                twos = ones;
                ones = max(0, cnt - tot);
                tot = cnt;
                cnt = 1;
            }
        }
        return ones == 0 && twos == 0;
    }
};

你可能感兴趣的:(IT公司面试习题)