leetcode2009--使数组连续的最少操作数

1. 题意

给定一个数组,求最少的操作数使得数组连续。

每次操作你可选择一个数,将它变为任意其他数。

leetcode2009

2. 题解

思路:反向考虑,最多能保留多少个数字使得当前数组连续。

就变成了 [ x , x + s z − 1 ] [x,x+sz-1] [x,x+sz1]的滑动窗口,最多包含了几个数组中的数字。

还有需要去重,重复的数字一定需要一次来改变。

最后的答案即 s z − m a x _ n u m b e r _ i n _ w i n d o w sz-max\_number\_in\_window szmax_number_in_window

其中有序数组去重对应leetcode26–删除有序数组重复项

2.1 排序+去重+滑动窗口

class Solution {
public:
    int minOperations(vector<int>& nums) {
        sort(nums.begin(), nums.end());

        int sz = nums.size();

        int cnt = 0;
        for (int i = 1; i < sz; ++i) {
            if ( nums[i] != nums[cnt]) {
                nums[++cnt] = nums[i];
            }
        }


       cout << cnt  + 1<< endl;
        int l = 0;
        int ans = 0;

        for (int i = 1; i < cnt + 1; ++i) {
            if ( nums[i] - nums[l] > sz - 1) {
                ans = max(ans, i - l);

                while (i < cnt + 1 && nums[i] - nums[l] > sz - 1)
                    ++l;
            }
        }


        ans = max(ans, cnt + 1 - l);



        return sz - ans;
    }
};
2.2 排序+去重+二分

可以固定左边界,二分寻找右边界。

class Solution {
public:
    int minOperations(vector<int>& nums) {
        sort(nums.begin(), nums.end());

        int sz = nums.size();

        int cnt = 0;
        for (int i = 1; i < sz; ++i) {
            if ( nums[i] != nums[cnt]) {
                nums[++cnt] = nums[i];
            }
        }


        int l = 0;
        int ans = sz;

        for (int i = 0; i < cnt + 1; ++i) {
        
                int l = i + 1;
                int r = cnt + 1;

                while ( l < r) {
                    int m = l + (r -l >> 1);

                    if ( nums[m] - nums[i] <= sz - 1) {
                        l = m + 1;
                    }
                    else {
                        r = m;
                    }
                }
           
            ans = min(ans, sz -(l - i));
            
        }




        return ans;
    }
};
  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值