Leetcode 1703 Minimum Adjacent Swaps for K Consecutive Ones [Python]

题目很难,首先要用到一个思想就是一个线段上的几个点,到其中位数点的距离最近,这么个思想。其次是滑动窗口和某种距离和的O(1)时间内的更新和prefixsum的关系。
首先,我们记录下原nums中所有1的位置,这样我们把原array转化为了index of 1的array,我们使用类似于https://leetcode.com/problems/best-meeting-point/ LC 296题的思想,假设我们找到K个单位(也就是包含了K个1)的1的index,然后我们的做法是首先假设把全部的1都移动到这段K个1的index组成的subarray的中位数位置上。然后计算左右侧的点移动到中位数的点上的移动步数,然后往前滑动窗口,得到下一段K个个1的index组成的subarray,再次计算上属的距离。更新全局最小值。这里还有一个技巧是使用prefixsum来完成滑动窗口内的距离和的更新,原本我们每次滑动窗口后,需要重新计算这段的中位数和两侧点过来的距离,但是这样时间复杂度高,尤其是k很大哦的时候,time complex变为O(n^2)。使用1的indexarray前缀和。就可以O (1) 时间完成更新。也就是prefixsum[i+k] - prefixsum[i+(k+1)//2] - (prefixsum[i+k//2] - prefixsum[i])。最后还需要注意,因为实际上我们左右两侧的1不用移动到中位数1的位置上,所以,我们其实多计算了距离,具体是多少呢,是((1+k)//2)*(k//2)。

可以画图帮助理解prefixsum的操作。假设k - 5. 如同下图所示,
假设我们有0到5共6个点的1的位置。在k=5的情况下,第一个窗口内的距离就是0,1,3,4到点2的距离和也就是也就是R1 + 2R2 + 2R3 + R4。下一个窗口的距离是R2 + 2R3 + 2R4 + R5.图中列出了,到各个位置的前缀和用Ri来表示。用P[5] - P[3] - (P[2]- P[0]) = R2 + 2R3 + 2R4 + R5**, 可以得到同样的答案。具体证明过程我也不会。。总之滑动窗口内的距离和就可以这样以前缀和的加减操作得到。

class Solution:
    def minMoves(self, nums: List[int], k: int) -> int:
        res = float('inf')
        index_1 = []
        for idx, num in enumerate(nums):
            if num == 1:
                index_1.append(idx)
            
        prefixsum = [0]
        for i in range(len(index_1)):
            prefixsum.append(prefixsum[-1] + index_1[i])
        
        
        for i in range(len(index_1)-k+1):
            temp = prefixsum[i+k] - prefixsum[i+(k+1)//2] - (prefixsum[i+k//2] - prefixsum[i])
            res = min(res, temp)
            
        res -= ((1+k)//2)*(k//2)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值