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

忙着期末,现在又在实习,太久没刷 leetcode了,今后还会坚持刷下去的。
思路:
这道题不太懂考什么,大概就是先排序,判断第一个是否为1,不为1就减小为1,然后循环到最后一个元素,判断是否相邻元素差值的绝对值是否小于等于1.

代码:

class Solution {
public:
    int maximumElementAfterDecrementingAndRearranging(vector<int>& arr) {
        sort(arr.begin(),arr.end());
        if(*arr.begin() != 1){
            *arr.begin() = 1;
        }
        int len = arr.size();
        for(int i=1;i<len;i++){
            if(abs(arr[i]-arr[i-1])>1){
                arr[i] = arr[i-1] + 1;
            }
        }
        return arr[len-1];
    }
};

还有一种很巧妙的贪心
直接在for循环里更改

for(int i=1;i<=len;++i){
  arr[i] = min(arr[i],arr[i-1]+1)
}

上述的方法的时间复杂度和排序的速度有关,大概是O(nlogn)
下面的方法能在O(n)解决
我们可以发现,按照题目的要求,可能的最大的数小于等于n,n是arr的长度。
所以有两种情况,第一种是最大的数等于n,也就是从1-n,每个数都有。第二种,一个数重复出现,此时就小于n。
所以我们用一个数组cnt来计数,记录arr里出现的数的数量,当数大于n时,就取为n即可。
那么我们再遍历这个cnt,如果发现没出现的数,就让计数的变量equalnums加一,因为不出现的原因可能大于也可能等于。当出现发现cnt的某一项大于1,说明有重复,那么我们就能让equalnums - min(cnt[i]-1,equalnums),前者-1是因为要留下一个数在该位置,剩下的可以减小来填补空缺的数,如果空缺的数小于能填补的数,那只需要把空缺的数填满即可,所以要取两者最小值
最后剩下的equalnums 用 n减即可。最后的结果就是,如果equalnums=0,那么就相当于没有空缺的数,最大的就为n,如果不等于0,那么就存在相等的数,用n-equalnums就可获得最大的数

代码:

class Solution {
public:
    int maximumElementAfterDecrementingAndRearranging(vector<int>& arr) {
        int n = arr.size();
        vector<int> cnt(n+1);
        for(int a : arr){
            cnt[min(a,n)]++;
        }
        int equalnums = 0;
        for(int i=1;i<=n;i++){
            if(cnt[i]==0){
                equalnums++;
            }
            else
            equalnums -= min(cnt[i]-1,equalnums);
        }
        return n - equalnums;
    }
};
posted @ 2021-07-15 14:09  Mrsdwang  阅读(36)  评论(0编辑  收藏  举报