分割数组为连续子序列

题目


给你一个按升序排序的整数数组 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]

原题跳转链接

解题思路


第一遍自己没有做出来,看了题解后选择了使用双哈希表,加贪心算法。具体思路如下:

  • 使用两个哈希表,第一个用来统计每个数字出现的次数。第二个用来统计以每个数字结尾的子串的数量,
  • 在第一次循环,初始化第一个哈希表。
  • 第二次循环开始判断,首先取出第i个数字,判断该数字剩余未使用的次数,如果已经为0,则跳过到下一个数字继续判断。
  • 如果第i个的未使用次数不为0,此时要分为两种情况。
    1. 判断是否有以第i - 1结尾符合要求的子串,如果有将第二个哈希表中以i - 1结尾的子串数量减1,以i结尾的子串数量加1。
    2. 如果此时没有以i - 1结尾的子串,则需要用该数字做为头,i + 1,i + 2组成新的子串,如果i + 1,i + 2的未使用次数小于0,则返回false。否则将第二个哈希表中以i + 2结尾的子串数量加1。

具体代码如下

struct hashTable{
    int val;
    int key;
    UT_hash_handle hh;
    /* data */
};

struct hashTable* find(struct hashTable** hashtable, int key){
    struct hashTable* tmp = malloc(sizeof(struct hashTable));
    HASH_FIND_INT(*hashtable, &key, tmp);
    return tmp;
}

void insert(struct hashTable** hashtable, int key, int val){
    struct hashTable* tmp = malloc(sizeof(struct hashTable));
    tmp->key = key;
    tmp->val = val;
    HASH_ADD_INT(*hashtable, key, tmp);
}
/*初始化第一个计数哈希表*/
void initial(struct hashTable** hashtable, int key){
    struct hashTable* tmp = find(hashtable, key);
    if (tmp == NULL){
        insert(hashtable, key, 1);
    }else{
        tmp->val++; 
    }
    
}
int sum_count(struct hashTable** hashtable, int key){
    struct hashTable* tmp = find(hashtable, key);
    if (tmp == NULL){
        return 0;
    }else{
        return tmp->val;
    }
}

void lin(struct hashTable** hashtable, int key, int val){
    struct hashTable* tmp = find(hashtable, key);
    if (tmp == NULL){
        insert(hashtable, key, val);
    }else{
        tmp->val = val;
    }
}

void ins(struct hashTable** hashtable, int key){
    struct hashTable* tmp = find(hashtable, key);
    if (tmp == NULL){
        insert(hashtable, key, 1);
    }else{
        tmp->val++;
    }
    
}

bool isPossible(int* nums, int numsSize){
    struct hashTable* countHash = NULL;
    struct hashTable* endHash = NULL;
    //初始化第一个哈希
    for(int i = 0; i < numsSize; i++){
        initial(&countHash, nums[i]);
    }
    //开始判断,并初始化第二个哈希
    for (int i = 0; i < numsSize; i++){
        //判断当前数字未使用次数
        int count = sum_count(&countHash, nums[i]);
        if (count > 0){
            //判断是否有以前一个数结尾的子串
            int precount = sum_count(&endHash,nums[i]- 1);//如果用num[i - 1]可能会越界
            if(precount > 0){
                lin(&countHash, nums[i], count - 1);//次数减一
                lin(&endHash, nums[i] - 1, precount - 1);
                ins(&endHash, nums[i]);
            }else{
                int count_1 = sum_count(&countHash, nums[i] + 1);
                int count_2 = sum_count(&countHash, nums[i] + 2);
                if(count_1 > 0 && count_2 > 0){
                    lin(&countHash, nums[i], count - 1);
                    lin(&countHash, nums[i] + 1, count_1 - 1);
                    lin(&countHash, nums[i] + 2, count_2 - 1);
                    ins(&endHash, nums[i] + 2);
                }else{
                    return false;
                }
            }
            
        }
        
    }
    return true;
}
posted @ 2020-12-05 15:39  爱吃_🍓  阅读(172)  评论(1)    收藏  举报