文章目录

  • 题目分析
  • 题目链接

题目分析

首先需要明确一点:最优结果中1的相对位置和开始时不会改变。否则的话就是交换两个1,会徒劳增加交换次数。 比如[1,0,0,0,0,0,1,1],最后变成[0,0,0,0,0,1,1,1],在变化过程中,哪个1在前哪个1在后是不会变的(不管0),即相对顺序不变。

问题变为,需要经过多少次移动,可以把k个分散的1变成k个连续的1(坐标连续)。 原下标分别是a0,a1,...ak−1a_0,a_1,...a_{k-1}a0​,a1​,...ak−1​分别移动到下标是x,x+1,x+2,...x+k−1x,x+1,x+2,...x+k-1x,x+1,x+2,...x+k−1(相对位置没变)的地方,使之移动次数最少,即求一个 x 使下式
d=∣a0−x∣+∣a1−(x+1)∣+....+∣ak−1−(x+k−1)∣d= |a_0-x|+|a_1-(x+1)|+....+|a_{k-1}-(x+k-1)|d=∣a0​−x∣+∣a1​−(x+1)∣+....+∣ak−1​−(x+k−1)∣
最小

再转化一下,变成到点x的距离之和

d=∣a0−x∣+∣(a1−1)−x∣+∣(a2−2)−x∣....+∣(ak−1−(k−1)−x∣d= |a_0-x|+|(a_1-1)-x|+|(a_2-2)-x|....+|(a_{k-1}-(k-1)-x|d=∣a0​−x∣+∣(a1​−1)−x∣+∣(a2​−2)−x∣....+∣(ak−1​−(k−1)−x∣

令:
a0′=a0a1′=a1−1...ak−1′=ak−1−(k−1)a_0'= a_0 \\ a_1'=a_1 -1 \\ ... \\ a_{k-1}'= a_{k-1} - (k-1)a0′​=a0​a1′​=a1​−1...ak−1′​=ak−1​−(k−1)

这里的映射是ai−ia_i - iai​−i,其中aia_iai​是“1”在原序列里的下标,表示第i+1i+1i+1个"1"的下标,比如第1个“1”的下标记作a0a_0a0​,此时i=0i=0i=0
就变成了d=∣a0′−x∣+∣a1′−x∣+∣a2′−x∣....+∣(ak−1′−x∣d= |a_0'-x|+|a_1'-x|+|a_2'-x|....+|(a_{k-1}'-x|d=∣a0′​−x∣+∣a1′​−x∣+∣a2′​−x∣....+∣(ak−1′​−x∣

这样就可以用绝对值不等式(母题:货仓选址)的模板,该式的最小值在 x 取a0′,a1′,...,ak−1′a_0',a_1',...,a_{k-1}'a0′​,a1′​,...,ak−1′​的中位数的时候取。

下面还有1个问题, 对于长度是k的区间[al,a2,amid..ar][a_l,a_2,a_{mid}..a_r][al​,a2​,amid​..ar​],如何快速求出上面绝对值求和的最小值,最小值是x取到中位数amida_{mid}amid​。 求和分两段:amida_{mid}amid​左边都是小于等于amida_{mid}amid​的,右边都是大于等于它的。这样可以省去绝对值的计算。

左边求和:left = (amid−al)+(amid−al+1)+...+(amid−amid−1)=amid∗(mid−l)−(s[mid−1]−s[l−1])(a_{mid}-a_{l}) + (a_{mid}-a_{l+1})+...+(a_{mid}-a_{mid-1}) \\ =a_{mid}*(mid-l)-(s[mid-1]-s[l-1])(amid​−al​)+(amid​−al+1​)+...+(amid​−amid−1​)=amid​∗(mid−l)−(s[mid−1]−s[l−1]),s为a序列的前缀和。

右边求和: right =(amid+1−amid)+....+(ar−amid)=s[r]−s[mid]−amid∗(r−mid)(a_{mid+1}-a_{mid})+....+(a_r - a_{mid})\\=s[r]-s[mid]-a_{mid}*(r-mid)(amid+1​−amid​)+....+(ar​−amid​)=s[r]−s[mid]−amid​∗(r−mid)

所以,这个窗口内移动次数 为 left + right .

以上只是一个窗口内的处理。 我们需要不断维护滑动窗口,k个1是一个窗口。

ac代码

class Solution {public:int minMoves(vector<int>& nums, int k) {vector<int> a;for(int i=0;i< nums.size();i++){if(nums[i])  //  找出1a.push_back(i-a.size());  // 坐标映射 第m个数的下标为i: i- m}int n=a.size();//n表示1的个数typedef long long LL;vector<LL> s(n+1);//前缀和数组for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i-1]; //下标从1开始LL res=1e18; //记录结果:最少移动次数//枚举所有窗口,窗口大小为k,这里枚举的是右端点for(int i=k;i<=n;i++){//左端点int l=i-k+1;//右端点int r=i;int mid = (l+r)/2;LL x = a[mid -  1] ; // for循环下标相当于从1开始,需要-1,因为遍历窗口的时候i=k,如果下标是从0开始的话,i应该为i= k-1.LL  left = x*(mid -l )-(s[mid-1 ] - s[l-1]);LL right = s[r]-s[mid] -x*(r-mid);res = min ( res , left+ right);}return res;}
};

下面是 对于滑动窗口k 枚举左端点,只要注意好 前缀和求和时候 和下标的关系!!因为前缀和数组下标从1开始!

class Solution {public:int minMoves(vector<int>& nums, int k) {typedef long long LL;LL res =1e17;vector<int >a;for(int i=0;i<nums.size();i++)if(nums[i]) a.push_back(i-a.size());int n=a.size();//统计1的个数vector<LL> s(n+1);for(int i=1;i<=n;i++) s[i] = s[i-1] + a[i-1];//枚举滑动窗口左端点for(int i=0;i+k-1<n;i++){int l = i ;int r = i+k -1;int mid =  l+r >> 1;int x = a[mid] ;LL left = x *(mid - l) -(s[mid]-s[l]);LL right = s[r+1]- s[mid+1] - x*(r -mid);res = min ( res, left+right);}return res;}
};

题目链接

Leetcode1703. 得到连续 K 个 1 的最少相邻交换次数

Leetcode1703. 得到连续 K 个 1 的最少相邻交换次数[C++题解]:难(货仓选址加强版+滑动窗口+前缀和)相关推荐

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

    贪心 将至少连续 K K K 个 1 1 1 放在一起.首先考虑他们是相邻着放在一起的,然后考虑性质 : 设相邻摆放后,起始 1 1 1 的位置是 m i d {mid} mid ,对于每个 1 1 ...

  2. 【Leetcode数组--子数组--滑动窗口】209. 长度最小的子数组 904. 水果成篮 1004. 最大连续1的个数 III 76. 最小覆盖子串(有数组操作中重要的方法:滑动窗口!!!!)

    文章目录 Leetcode209 1.问题描述 2.解决方案 解法一:两个错误思路的算法 解法二:暴力 解法三:滑动窗口法(O(n)) Leetcode904 1.问题描述 2.解决方案 Leetco ...

  3. LeetCode 1151. 最少交换次数来组合所有的 1(滑动窗口)

    文章目录 1. 题目 2. 解题 1. 题目 给出一个二进制数组 data,你需要通过交换位置,将数组中 任何位置 上的 1 组合到一起,并返回所有可能中所需 最少的交换次数. 示例 1: 输入:[1 ...

  4. 通过交换相邻数来完成排序所需要的最少交换次数

    对一个无序序列进行排序,要求一次只能交换相邻的两个数,那么最少需要交换多少次才可以完成排序呢? 本问题假设序列所有数各不相同. 概念介绍: 1.逆序.一般认为从左向右序列的数字增大认为是正序的,那么从 ...

  5. 2379. 得到 K 个黑块的最少涂色次数

    2379. 得到 K 个黑块的最少涂色次数 给你一个长度为 n 下标从 0 开始的字符串 blocks ,blocks[i] 要么是 'W' 要么是 'B' ,表示第 i 块的颜色.字符 'W' 和 ...

  6. 得到 K 个黑块的最少涂色次数

    leetcode 2379. 得到 K 个黑块的最少涂色次数 给你一个长度为 n 下标从 0 开始的字符串 blocks ,blocks[i] 要么是 'W' 要么是 'B' ,表示第 i 块的颜色. ...

  7. LeetCode#2379. 得到 K 个黑块的最少涂色次数

    给你一个长度为 n 下标从 0 开始的字符串 blocks ,blocks[i] 要么是 'W' 要么是 'B' ,表示第 i 块的颜色.字符 'W' 和 'B' 分别表示白色和黑色. 给你一个整数  ...

  8. C练题笔记之:Leetcode-第 85 场双周赛---6156. 得到 K 个黑块的最少涂色次数

    题目: 给你一个长度为 n 下标从 0 开始的字符串 blocks ,blocks[i] 要么是 'W' 要么是 'B' ,表示第 i 块的颜色.字符 'W' 和 'B' 分别表示白色和黑色. 给你一 ...

  9. sscanf 连续相同编辑符_基于单调栈的滑动窗口法求解“和至少为 K 的最短连续子数组”...

    题目解读 题目要求我们给出一个最短的连续子数组,且这个子数组的和要大于等于 K.乍一看,除了暴力,似乎没什么思路.由于数组规模为 50000,暴力肯定会超时的.但是,我们还是要先暴力一把,看看有什么灵 ...

最新文章

  1. R使用neuralnet包构建神经网络回归模型并与线性回归模型对比实战
  2. source insight 4.0 护眼背景色设置
  3. 回车与换行 ASCII
  4. python文件读取方法read(size)的含义是_在Python中可使用read([size])来读取文件中的数据,如果参数size省略,则读取文件中的()。(4.0分)_学小易找答案...
  5. kk服务器信息及端口,kk服务器设置
  6. 线程池原理_JAVA并发编程:详解线程池的工作原理
  7. css 电子数字字体
  8. 电音插件auto_自动电音基调查询软件助手完美支持32_64bit系统所有电音插件
  9. 如何辨别BGP带宽的真假?
  10. php 前端 java培训哪个好,php培训、前端培训、java培训哪个好
  11. 【转】程序员面试揭秘之程序员靠什么途径去美国工作?
  12. 微信小程序vantweapp-Dialog弹出框提交表单,并还原确定按钮样式
  13. anaconda企业版下载_Anaconda免费版下载-多功能Python集成开发环境 v2020.02 免费版 - 安下载...
  14. 港股开盘价是如何产生的
  15. 庄家高位出货的三种基本手法
  16. 计算机字长通常不可能,计算机的字长通常不可能为( )位。
  17. Social-STGCNN: A Social Spatio-Temporal GCNN for Human Trajectory Prediction(CVPR2020)论文阅读笔记
  18. 第三部,雨荨云海婚后故事概要
  19. 什么是DTO 什么是KYC
  20. 动态添加/删除HTML元素

热门文章

  1. linux 系统优化初始化配置
  2. Mongo报如下类似错误时的修改方法Cannot natively represent the long 1396367483000 on this platform...
  3. 论计算机在教学中的作用论文,计算机在教学中的应用
  4. 计算机无法识别华为m3,华为8寸M3(非青春版)电脑连接问题报告
  5. 【控制】《复杂运动体系统的分布式协同控制与优化》-方浩老师-第7章-带有操作度及能量优化的分布式协同搬运控制
  6. 5.2 大间距分类器-机器学习笔记-斯坦福吴恩达教授
  7. ISE_软件基本使用流程(win10 的bug工程约束仿真烧写mcs固化)
  8. 少儿编程教会孩子如何思考,重视孩子的素质提升
  9. 【PC工具】更新百度网盘高速下载工具——亿寻使用方法及注意事项
  10. 北京、广东重名数量查询工具,给孩子起名重名查询