【LeetCode - 1121】将数组分成几个递增序列

1、题目描述

在这里插入图片描述

2、解题思路

  题目要求分成一个或者若干个递增子序列,递增子序列有两个特定:从小到大递增、元素不重复。

  因此,给定一个数组 nums,假设里面的元素重复次数最多的是数字 x,它重复了 count 次,那么,至少得有 count 个子序列,如果低于 count 个子序列,一定会有子序列有重复的 x 存在。

  先把 nums 拆成若干个递增子序列。

  1、先从 nums 中找出重复次数最多的数字,假设为 i,重复了 max 次;

  2、创建 max 个子序列,然后把这 max 个 i 平均分配给每一个子序列;

  3、把 nums 中剩余的元素平均分配给每一个子序列。

  以一个例子来说明上面三步,比如:nums = {1,2,2,3,3,4,4,5,6,7}

  1、重复次数最多的是 2、3、4,都重复了 2 次;

  2、创建 2 个子序列 {} 、{},把 2、3、4 平均分配给每一个子序列,变为{2,3,4} 和 {2,3,4}

  3、nums 剩余元素为 {1,5,6},轮流分配给每一个子序列:

  {2,3,4} + 1 = {1,2,3,4}

  {2,3,4} + 5 = {2,3,4,5}

  {1,2,3,4} + 6 = {1,2,3,4,6}

  最终的结果就是 {1,2,3,4,6} 和 {2,3,4,5}。

  回到题目要求,子序列长度至少为 K,如果 K 为 3,我们上面两个子序列都满足要求,返回 true;如果 K 为 5 ,则{2,3,4,5}不满足要求,返回false。

  代码并不用按照上面这样一步步操作,我们只需要使用反证法即可。

  找出 nums 中出现次数最大的数字 i 和对应的出现次数 max,创建 max 个子序列。

  因为子序列的个数至少是 count 个,最短的子序列长度至少为 K。

  如果要满足题目要求,那么所有子序列的元素个数加起来至少为 max × K 个,且子序列的所有元素均来自于 nums。

  因此,如果 max × K <= nums.length ,那么一定满足题目要求,反之一定不满足。

  这里解释一下为什么:当我们创建了 max 个子序列并把重复了 max 次的数字 i 分配完,这时,nums 剩余元素个数为 residue = nums.length - max,这 residue 个元素是按照从小到大依次分配给每一个子序列,因此子序列不会有重复的数字,并且子序列的元素个数差最多为 1。
在这里插入图片描述
  当 max × K == nums.length,说明刚好满足题目要求,若 nums 的元素个数不足 max × K 个元素,则一定不满足要求。若 nums 的元素个数大于 max × K,说明不及满足,还绰绰有余。

3、解题代码

class Solution {
    public boolean canDivideIntoSubsequences(int[] nums, int K) {
        int max = 1;    // 最长重复元素个数
        int temp = 1;   // 当前元素重复个数
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == nums[i - 1]) {
                temp++;
            } else {
                max = Math.max(max, temp);
                temp = 1;
            }
        }
        max = Math.max(max, temp);
        return max * K <= nums.length;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值