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:
- The length of the input is in range of [1, 10000]
思路一:直接求解,TLE,这种直接求解的问题在于,如果当前nums[i]值对于多个list都满足要求的时候,需要遍历全部的list集合,因为不确定后面是否存在少于3个值的list,因此效率很低,针对这点可以做两点优化,一个是不要用list,直接用数组表示,如思路二,另一个是通过一个HashMap实现,如思路三。程序如下所示:
class Solution {
public boolean isPossible(int[] nums) {
if (nums.length < 3){
return false;
}
List<List<Integer>> list = new ArrayList<>();
List<Integer> l = new ArrayList<>();
l.add(nums[0]);
list.add(l);
int index = 0;
for (int i = 1; i < nums.length; ++ i){
index = -1;
for (int j = 0; j < list.size(); ++ j){
List<Integer> t = list.get(j);
if (t.get(t.size() - 1) == nums[i] - 1){
if (t.size() < 3){
t.add(nums[i]);
index = -2;
break;
}
index = j;
}
}
if (index >= 0){
list.get(index).add(nums[i]);
}
else if (index == -1){
List<Integer> tmp = new ArrayList<>();
tmp.add(nums[i]);
list.add(tmp);
}
}
for (List<Integer> t : list){
if (t.size() < 3){
return false;
}
}
return true;
}
}
思路二:用数组替换思路一的list,可AC,但效率仍比较低,因为时间复杂度并没有降低,程序如下所示:
class Solution {
public boolean isPossible(int[] nums) {
if (nums.length < 3){
return false;
}
int[][] dp = new int[nums.length][2];
dp[0][0] = 1;
dp[0][1] = nums[0];
int len = 1;
for (int i = 1; i < nums.length; ++ i){
int index = -1;
for (int row = 0; row < len; ++ row){
if (dp[row][1] == nums[i] - 1){
if (dp[row][0] < 3){
dp[row][1] = nums[i];
dp[row][0] ++;
index = -2;
break;
}
index = row;
}
}
if (index >= 0){
dp[index][0] ++;
dp[index][1] = nums[i];
}
else if (index == -1){
dp[len][0] ++;
dp[len][1] = nums[i];
len ++;
}
}
for (int i = 0; i < len; ++ i){
if (dp[i][0] < 3){
return false;
}
}
return true;
}
}
思路三:注意思路二,可以通过两个元素来表示一个连续递增的序列,一个是size,另一个值是最末尾的值,那么,可以通过一个HashMap来表示,其中key值是当前序列最末尾的值(序列最大值),value值对应该序列的长度。具体实现就不给出了。