【滑动窗口】“正难则反法” 解决最小操作数的问题

2023-10-18 17:12

本文主要是介绍【滑动窗口】“正难则反法” 解决最小操作数的问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

Problem: 1658. 将 x 减到 0 的最小操作数

文章目录

  • 题目解析
  • 算法原理分析
  • Code
  • 复杂度

题目解析

首先我们来解读一下本题的题目含义

  • 题目会给到我们一个整数数组和一个整数x,我们可以从左侧,也可以从右侧去减,只要让这个x最终减到【0】即可。
  • 不过呢既然可以从左边也可以从右边减的话就一定存在多种方案,我们所需要的话是操作次数最少的那次,看到下面我列出来的两种情况,很明显第二种方法 从右侧删去两个数据更加优的

1.jpg

算法原理分析

接下去我们来介绍一下本题的算法原理

  • 通过刚才的分析相信很多小伙伴认为本题的题目意思并不是很难理解,但是呢想找到对应的解决方案还是比较困难的,在这里的话教大家一种方法叫做 “正难则反法"
  • 题目中要我们去找的是左右两侧的 最小操作数,但是呢这并不好计算,于是我们可以换个思路,将左侧的数据看做是一个整体,记为a;将右侧的数据看做是一个整体,记为b;那么我们可以得出a + b = x
  • 既然左右两侧的是x的话,那么中间的一段就是sum - x。而且既然两边需要最短的话,中间我们要找的就是【最长的那一段】

2.jpg

  • 因此经过上面的步步分析,我们便将题目的意思转换为了去找 数组里面最长子数组的长度,而且它们的和即为sum - x的结果。不过最后我们要返回的结果可不是这个长度len,而是n - len

3.jpg

  • 本题我们还是考虑使用滑动窗口来进行求解,因为滑动窗口本身就是基于【双指针】的,所以读者在看此文的时候可以先看看我『双指针』的专栏题解
  • 我们的right指针还是一样作为向后遍历并进行计数累加的指针,当其没有达到target的时候就继续去作累加的操作,这相当于是【进窗口】的操作。当其到中间这个点的时候此时sum的值只会是 大于或者等于target
  • sum == target 的时候呢便去做更新长度的操作。当sum > target的时候我们就要去考虑【出窗口】的操作,将左侧的left指针所指向的内容从我们所累加的和中减去,然后还需要执行left++让其继续后移

4.jpg

那有同学问:right还需要回来吗,还是持续后移呢?

  • 我们来探讨一下这个问题,因为在中间这个点的时候sum >= target,那从最左侧到这个点前面一个点的总和是< target的,那如果我们使用暴力解法的话在left向后移动的时候,此时如果right再回来的话,其实是没有必要了,因为left++执行了出窗口的操作后,这个sum就更为小了,此时让right--再左移的话只会更小
  • 所以我们的和这个right是不需要回来的,它只会在那个== target的位置或者是> target的位置

5.jpg

💬 最后的代码详解我们马上来看看看【code】部分,不过读者可以根据算法原理的解读自己试着写写看

Code

对于代码而言的话读者基本上就是根据我们前面所描述的去进行书写即可,还有一些细节地方需要注意

  • 题目中给到的提示这一块,即数组里面所有的数据都是大于1的,那么我们数组中找这个target的时候是不会出现负数这种情况的,所以若是遇到这种情况的,我们直接return -1即可

6.jpg

以下是整体的代码详解:


class Solution {
public:int minOperations(vector<int>& nums, int x) {int n = nums.size();int sum1 = 0;    // 用于先行求出整个数组的和int sum2 = 0;    // 用于遍历数组时的累加int ret = -1;for(int a : nums)   sum1 += a; int target = sum1 - x;      // 减去两端的数据后中间的和// 处理细节:数组中不会存在负数, 若存在的话则表示找不到if(target < 0)  return -1;for(int left = 0, right = 0; right < n; ++right){// 1.进窗口sum2 += nums[right];// 累加和超过target则开始出窗口while(sum2 > target){// 2.出窗口sum2 -= nums[left++]; }// 3.更新结果if(sum2 == target)ret = max(ret, right - left + 1);}if(ret == -1)   return ret;elsereturn n - ret;    // 减去最长的子串即为最小操作数}
};

下面则是执行的结果:

7.jpg

复杂度

最后我们来谈一下复杂度这一块

  • 时间复杂度:

对于时间复杂度我们在一开始做了遍历,去累加数组中的和,后面呢又去遍历了一下这个数组,结合一下最后的复杂度还是 O ( n ) O(n) O(n)

  • 空间复杂度:

对于空间复杂度来说,我们并没有开辟出多余的空间,即为 O ( 1 ) O(1) O(1)

在这里插入图片描述

这篇关于【滑动窗口】“正难则反法” 解决最小操作数的问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/234014

相关文章

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri