力扣(LeetCode)1703. 得到连续 K 个 1 的最少相邻交换次数(C++)

贪心

将至少连续 K K K 1 1 1 放在一起。首先考虑他们是相邻着放在一起的,然后考虑性质 : 设相邻摆放后,起始 1 1 1 的位置是 m i d {mid} mid ,对于每个 1 1 1 的位置 a i a_i ai ,它需要被摆放的位置是 a m i d + i a_{mid}+i amid+i 。考虑一个等价代换,令 a i ′ = a i − i a^{'}_i = a_i - i ai=aii ,那么 a i ′ a^{'}_i ai a m i d a_{mid} amid 的距离等于 a i a_i ai a m i d + i a_{mid}+i amid+i 的距离。这一步固定了待求距离的点。

记录所有 1 1 1 位置,存于数组 a a a ,每次考虑 K K K 个连续的 1 1 1 ,即 R − L + 1 = K R-L+1=K RL+1=K 。可以证明,要使距离之和最小,只要取中间点即可 (贪心货仓选址)。

先分段讨论,对于左端,距离之和有 : ( a m i d − a L ) + ( a m i d − a L + 1 ) + ⋯ + ( a m i d − a m i d − 1 ) = a m i d × ( m i d − L ) − ( S m i d − S L − 1 ) (a_{mid} - a_{L})+(a_{mid} - a_{L+1})+\dots+(a_{mid} - a_{mid-1})=a_{mid} \times (mid-L)-(S_{mid}-S_{L-1}) (amidaL)+(amidaL+1)++(amidamid1)=amid×(midL)(SmidSL1) 。其中 S S S 是前缀和数组。由连续项,想到前缀和。

对于左端,距离之和有 : ( a m i d + 1 − a m i d ) + ( a m i d + 2 − a m i d ) + ⋯ + ( a R − a m i d ) = ( S R − S m i d ) − a m i d × ( R − m i d ) (a_{mid+1} - a_{mid})+(a_{mid+2} - a_{mid})+\dots+(a_{R} - a_{mid})=(S_{R}- S_{mid})-a_{mid} \times (R-mid) (amid+1amid)+(amid+2amid)++(aRamid)=(SRSmid)amid×(Rmid)

综上,距离之和 a m i d × ( 2 × m i d − r − l ) + s r − s m i d − s m i d − 1 + s l − 1 ) a_{mid}\times(2\times mid-r-l) + s_r - s_{mid} - s_{mid-1} + s_{l-1}) amid×(2×midrl)+srsmidsmid1+sl1)

class Solution {
public:
    int minMoves(vector<int>& nums, int k) {
        vector<int> a;
        for(int i = 0 ;i< nums.size();i++)
            if(nums[i])
                a.push_back(i-a.size());
        int n = a.size();
        int s[n+1];
        for(int i = 1;i<=n;i++)
            s[i] = s[i-1]+a[i-1];
        int ans = INT_MAX ;
        for(int l = 1;l<=n-k+1;l++){
            int r = l + k - 1;
            int mid = (l+r)>>1;
            ans = min(ans,a[mid-1]*(2*mid-r-l) + s[r] - s[mid] - s[mid-1] + s[l-1]);
            //由于求了前缀和,a对应的下标要左移1.
        }
        return ans;
    }
};
  1. 时间复杂度 : O ( n ) O(n) O(n) n n n 是数字总数,一次遍历找 1 1 1 ,构造前缀和,遍历 1 1 1 的时间复杂度 O ( n ) O(n) O(n)
  2. 空间复杂度 : O ( n ) O(n) O(n) , 存储 1 1 1 ,前缀和的空间复杂度 O ( n ) O(n) O(n)
AC

AC

致语
  • 理解思路很重要
  • 读者有问题请留言,清墨看到就会回复的。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清墨韵染

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值