文章目录
分割数组为连续自序列
给你一个按升序排序的整数数组 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
java
贪心思想:
先统计每个数组出现的频数, 存放在一个hashmap中, (例: 1 2 3 3 4 4 5)
则现在map = {1:1,2:1,3:2,4:2,5:1}
HashMap<Integer,Integer> mmp = new HashMap<>();
for(int i : nums) {
if (!mmp.containsKey(i)) {
mmp.put(i, 1);
} else {
mmp.put(i, mmp.get(i) + 1);
}
}
根据贪心思想, 每次取一个连续数字, 如果数字不联系, 则跳出循环, 产生一个子序列, 但是根据上面的例子, 12345都连续,到底取到哪一个数字停呢,
根据贪心思想,虽然取刀不能连续, 但也要保证后面出现频率较少的数字跟着下一轮遍历 , 这样就可以保证最优化的子序列:
if(!mmp.containsKey(key+1)||mmp.get(key+1)<=mmp.get(key)){
break;
}
第一次取得 1 2 3 4 . 而不是 12345, map中剩余元素{ 3: 1, 4: 1 , 5: 1};
下一次循环则将map遍历完成.
while (mmp.size()>0){
//int key = nums[0];
int key = minKey(mmp);
int lennow = 0;
while (mmp.containsKey(key)){
mmp.put(key,mmp.get(key)-1);
lennow++;
if(!mmp.containsKey(key+1)||mmp.get(key+1)<=mmp.get(key)){
break;
}
key++;
}
if (lennow<3)return false;
deleteValueIsZero(mmp);
}
中间需要用到两个自己写方法:
minKey(): 获取mmp中的最小的key
public static int minKey(HashMap<Integer,Integer> mmp){
int min = Integer.MAX_VALUE;
for(int item: mmp.keySet()){
if(item<min){
min = item;
}
}
return min;
}
maxKey(): 获取mmp中最大的key
public static int maxKey(HashMap<Integer,Integer> mmp){
int max = Integer.MIN_VALUE;
for(int item: mmp.keySet()){
if(item>max){
max = item;
}
}
return max;
}
deleteValueIsZero():删除map中值为0的key
public static void deleteValueIsZero(HashMap<Integer,Integer> mmp){
int len = mmp.size();
int i = minKey(mmp);
while (i<maxKey(mmp)+1){
if(mmp.containsKey(i)){
if(mmp.get(i)==0){
mmp.remove(i);
}
}
i++;
}
}
完整代码
class Solution {
public boolean isPossible(int[] nums) {
if (nums.length<3)return false;
HashMap<Integer,Integer> mmp = new HashMap<>();
for(int i : nums) {
if (!mmp.containsKey(i)) {
mmp.put(i, 1);
} else {
mmp.put(i, mmp.get(i) + 1);
}
}
if(mmp.size()<3)return false;
while (mmp.size()>0){
//int key = nums[0];
int key = minKey(mmp);
int lennow = 0;
while (mmp.containsKey(key)){
mmp.put(key,mmp.get(key)-1);
lennow++;
if(!mmp.containsKey(key+1)||mmp.get(key+1)<=mmp.get(key)){
break;
}
key++;
}
if (lennow<3)return false;
deleteValueIsZero(mmp);
}
return true;
}
public static int minKey(HashMap<Integer,Integer> mmp){
int min = Integer.MAX_VALUE;
for(int item: mmp.keySet()){
if(item<min){
min = item;
}
}
return min;
}
public static int maxKey(HashMap<Integer,Integer> mmp){
int max = Integer.MIN_VALUE;
for(int item: mmp.keySet()){
if(item>max){
max = item;
}
}
return max;
}
public static void deleteValueIsZero(HashMap<Integer,Integer> mmp){
int len = mmp.size();
int i = minKey(mmp);
while (i<maxKey(mmp)+1){
if(mmp.containsKey(i)){
if(mmp.get(i)==0){
mmp.remove(i);
}
}
i++;
}
}
}
python
贪心算法:
因为统计再python中可以使用collections.Counter, 这个包中也有最大元素,最小元素的方法,所以很简单
class Solution:
def isPossible(self, nums: List[int]) -> bool:
if len(nums) < 3:
return False
if len(set(nums)) < 3:
return False
#统计
mmp = collections.Counter(nums)
while mmp:
key, lengths = min(mmp.keys()), 0
while (key in mmp): #依次检查是否有连续数字
mmp[key] -= 1
lengths += 1
#当后面的数字频数小于前面的数字时,则退出循环
if mmp[key+1] <= mmp[key]:
break
key += 1
if lengths < 3: return False
mmp += collections.Counter()
return True