LeetCode——1846. 减小和重新排列数组后的最大元素

减小和重新排列数组后的最大元素

题目

给你一个正整数数组 arr 。请你对 arr 执行一些操作(也可以不进行任何操作),使得数组满足以下条件:

arr 中 第一个 元素必须为 1 。
任意相邻两个元素的差的绝对值 小于等于 1 ,也就是说,对于任意的 1 <= i < arr.length (数组下标从 0 开始),都满足 abs(arr[i] - arr[i - 1]) <= 1 。abs(x) 为 x 的绝对值。
你可以执行以下 2 种操作任意次:

减小 arr 中任意元素的值,使其变为一个 更小的正整数 。
重新排列 arr 中的元素,你可以以任意顺序重新排列。
请你返回执行以上操作后,在满足前文所述的条件下,arr 中可能的 最大值 。

思路

为了使得最后的数字越大,先对其进行一个升序排序,假设说这个数组,能取到最大值的话,那么就是一个起始值为1,后面的数字比前面数值递增1的一个数组最后的那个数字能够取得最大值。

因为要求arr[0]必须为1,所以一开始先对其进行一个赋值!

我们进行了升序排序之后,后面的数字一定大于等于前面的数字!

局部最优化就是arr[i]=Math.min(arr[i],arr[i-1]+1);数组中相邻两个元素,要么后者等于前者,要么后者等于前者加上 1。这样就能使得最终的数字取得最大值!

思路

import java.util.Arrays;

class Solution {
    public int maximumElementAfterDecrementingAndRearranging(int[] arr)
    {
        int length=arr.length;
        Arrays.sort(arr); // 先进行一个升序排序
        if (arr[0]!=1)
            arr[0]=1;
        for (int i = 1; i < length; ++i)
        {
            // 为了使得越往后的数字越大,当前位置的数字必须越小越好,最小的情况就是跟前面的数字相同或者是后面的数字远远大于前面的数字,需要对其进行一个降低操作
            arr[i]=Math.min(arr[i], arr[i-1] + 1);
        }
        return arr[length-1];
    }
}

结果

在这里插入图片描述

题解思路

为了尽可能地构造出最大的答案,我们相当于是在用 arr 中的元素去填补自身在 [1,n]中缺失的元素。
首先,我们用一个长为 n+1的数组 cnt 统计 arr 中的元素个数(将值超过 n 的元素视作 n)。
然后,从 1 到 n 遍历 cnt 数组,若 cnt[i]=0,则说明缺失元素 i,我们需要在后续找一个大于 i 的元素,将其变更为 i。我们可以用一个变量miss 记录cnt[i]=0 的出现次数,当遇到 cnt[i]>0 时,则可以将多余的cnt[i]−1 个元素减小,补充到之前缺失的元素上。

遍历 cnt 结束后,若此时 miss=0,则说明修改后的 arr 包含了[1,n]内的所有整数;否则,对于不同大小的缺失元素,我们总是优先填补较小的,因此剩余缺失元素必然是[n−miss+1,n] 这一范围内的miss 个数,因此答案为n−miss。

题解代码

class Solution {
    public int maximumElementAfterDecrementingAndRearranging(int[] arr) 
    {
        int n = arr.length;
        int[] cnt = new int[n + 1];
        // 统计数值的数目,只统计从1到n的,因为数组的长度为n,就算数组是一个差值为1的等差数列,最终最大的值也只是n,其余那些都要回归到1到n的范围之内!
        for (int v : arr) {
            ++cnt[Math.min(v, n)];
        }
        // 统计哪些位置需要变化数字,当cnt的数值为0的时候,表明当前是没有数值的,就需要找一个数来进行补充,所以miss++;
        int miss = 0;
        for (int i = 1; i <= n; ++i) 
        {
            if (cnt[i] == 0)
             {
                ++miss;
            }
            // 如果当前数字不为0,因为题目要求只能减少不能增多,所以就需要这些位置的数值都放置他们原来的数值,最终统计出来的,就是需要变化位置使得其能够连续的个数
             else 
             {
                miss -= Math.min(cnt[i] - 1, miss); // miss 不会小于 0,故至多减去 miss 个元素
            }
        }
        // 本来最大值是n,需要有miss个数字去进行一个减少,返回减去的值即可!
        return n - miss;
    }
}

题解结果

在这里插入图片描述
题解果然牛,减少了时间复杂度和空间复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值