【1703. 得到连续 K 个 1 的最少相邻交换次数】
admin
2024-04-26 06:32:52
0

来源:力扣(LeetCode)

描述:

给你一个整数数组 nums 和一个整数 k 。 nums 仅包含 0 和 1 。每一次移动,你可以选择 相邻 两个数字并将它们交换。

请你返回使 nums 中包含 k 个 连续 1 的 最少 交换次数。

示例 1:

输入:nums = [1,0,0,1,0,1], k = 2
输出:1
解释:在第一次操作时,nums 可以变成 [1,0,0,0,1,1] 得到连续两个 1 。

示例 2:

输入:nums = [1,0,0,0,0,0,1,1], k = 3
输出:5
解释:通过 5 次操作,最左边的 1 可以移到右边直到 nums 变为 [0,0,0,0,0,1,1,1] 。

示例 3:

输入:nums = [1,1,0,1], k = 2
输出:0
解释:nums 已经有连续 2 个 1 了。

提示:

  • 1 <= nums.length <= 105
  • nums[i] 要么是 0 ,要么是 1 。
  • 1 <= k <= sum(nums)

方法:贪心 + 前缀和

思路

设数组 nums 的长度为 n,其中共有 m 个 1,它们在数组 nums 中的下标分别为 p0, p1, ,…, pm−1 。假设经过若干次交换后,数组 nums 中形成的 k 个连续的 1 的下标为 q, q + 1, …, q + k − 1。根据贪心的思想,要想交换次数最少,必须满足以下两个条件:

  • 这 k 个连续的 1 的起始下标在 p 数组中是连续的,即下标为 pi , pi+1 ,…, pi+k−1
  • k 个 1 的起始下标和结尾下标是按顺序对应的,即下标为 pi 的 1 交换到 q,下标为 pi+k−1 的 1 交换到 q + k - 1 ,中间的元素也需要按照顺序。

代码:

class Solution {
public:int minMoves(vector& nums, int k) {vector g;vector preSum(1, 0);for (int i = 0; i < nums.size(); i++) {if (nums[i] == 1) {g.emplace_back(i - g.size());preSum.emplace_back(preSum.back() + g.back());}}int m = g.size(), res = INT_MAX;for (int i = 0; i <= m - k; i++) {int mid = i + k / 2;res = min(res, (1 - k % 2) * g[mid] +  \(preSum[i + k] - preSum[mid + 1]) - \(preSum[mid] - preSum[i]));}return res;}
};

执行用时:100 ms, 在所有 C++ 提交中击败了89.80%的用户
内存消耗:122.6 MB, 在所有 C++ 提交中击败了14.96%的用户
复杂度分析
时间复杂度: O(n),其中 n 是数组 nums 的长度。
空间复杂度: O(n)。
author:LeetCode-Solution

相关内容

热门资讯

盘点下24小时正规一元一分红中... 加群主V:mj43567 或 QQ:384169851 或欢迎麻将爱好者来玩,二千多真实玩家,一元一...
推荐玩法正规一元一分红中麻将群... 群主微:mj33931或QQ:384169851欢迎麻将爱好者来玩,一局一清,真人实战,全网最公平公...
必玩科普正规24小时一元一分红... 加群主微信:mj43567 或QQ:384169851来玩就送福利,群内所有用户都是微信实名制玩家,...
打发时间一元一分红中麻将跑得快... 认准微——as099055或as022055——客服扣675434346免押%D%A
哪里有一元一分血战到底麻将群_... 微【ss28210】【vy23547【z36121】四川血战换三张红中推倒胡等麻将群,加微拉群 随...
全网玩一分1块红中麻将跑得快让... 认准微——as099055或as022055——客服扣675434346免押金、免费进
放假不休息手机娱乐16张跑得快... 加群主威【yb68468或cc355389】【qq707940021】(一块一分四川川嘛血战)(一元...
一元一分四川麻将上分群四川麻将... 红中麻将一元一分APP方式:认准微—VY23547—z36L2L——客服扣398233877免押金、...