Leetcode刷题209. 长度最小的子数组

news/2024/5/20 6:06:46 标签: 数组, 二分查找, 前缀和, 滑动窗口

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组
示例 2:

输入:target = 4, nums = [1,4,4]
输出:1
示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
 

提示:

1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
 

进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-size-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

感谢windliang的详细通俗的思路分析,多解法,感谢数据结构和算法的Java 的 5 种解法,最好的击败了 99.85% 的用户

 

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
//		return minSubArrayLenI(target, nums);
//		return minSubArrayLenII(target, nums);
		return minSubArrayLenIII(target, nums);
	}

	//方法三:前缀和+二分查找,时间复杂度O(NlogN),空间复杂度O(N)
	//由于数组元素都是正整数,定义新的数组sum[i],表示从0到i的累加和,这样就得到一个有序数组
	//通过sum数组,如果要求i到j的所有子数组的和,就等于前j个数字的和减去前i-1个数字的和,即sum[j]-sum[i-1]
	//与方法一类似,利用sum数组分别求出从0,1,2....个数字开始,总和大于等于target时的长度
	//比如求从第i个数字开始,总和大于等于target时的长度,sum[j]-sum[i-1] >= target -> sum[j] >= target + sum[i-1]
	private int minSubArrayLenIII(int target, int[] nums) {
		if (nums == null || nums.length == 0) {
			return 0;
		}
		int len = nums.length;
		int min = Integer.MAX_VALUE;
		int[] sum = new int[len + 1];
		for (int i = 1; i <= len; i++) {
			sum[i] = sum[i - 1] + nums[i - 1];
		}
		for (int i = 1; i <= len; i++) {
			int s = target + sum[i - 1];
			int index = findLeftBound(sum, s);
			if (index != -1) {
				min = Math.min(min, index - i + 1);
			}
		}
		return min == Integer.MAX_VALUE ? 0 : min;
	}

	private int findLeftBound(int[] nums, int target) {
		int len = nums.length;
		if (target < nums[0] || target > nums[len - 1]) {
			return -1;
		}
		int left = 0, right = len;
		while (left < right) {
			int mid = left + (right - left) / 2;
			if (nums[mid] < target) {
				left = mid + 1;
			} else {
				right = mid;
			}
		}
		return left;
	}

	//方法二:队列实现滑动窗口思想
	//先把数组中元素不停的入队,直到总和大于等于s为止,接着记录队列中元素的个数,然后再不停的出队,直到队列中元素的和小于s为止。
	//接着再把数组中的元素添加到队列中...重复上面的操作,直到数组中的元素全部用完为止
	//定义两个指针,分别指向队头和队尾
	//时间复杂度O(N),空间复杂度O(1)
	private int minSubArrayLenII(int target, int[] nums) {
		if (nums == null || nums.length == 0) {
			return 0;
		}
		int left = 0;
		int right = 0;
		int min = Integer.MAX_VALUE;
		int sum = 0;
		while (right < nums.length) {
			//不断入队
			sum += nums[right++];
			while (sum >= target) {
				//更新结果
				min = Math.min(min, right - left);
				//出队
				sum -= nums[left++];
			}
		}
		return min == Integer.MAX_VALUE ? 0 : min;
	}

	//方法一:暴力解法
	//遍历数组,分别计算数组中从第i个元素开始的总和,如果出现大于等于s则比较其长度,得出最小值
	//时间复杂度O(N^2),空间复杂度O(1)
	private int minSubArrayLenI(int target, int[] nums) {
		if (nums == null || nums.length == 0) {
			return 0;
		}
		int min = Integer.MAX_VALUE;
		for (int i = 0; i < nums.length; i++) {
			int sum = nums[i];
			if (sum >= target) {
				return 1;
			}
			for (int j = i + 1; j < nums.length; j++) {
				sum += nums[j];
				if (sum >= target) {
					min = Math.min(min, j + 1 - i);
					break;
				}
			}
		}
		return min == Integer.MAX_VALUE ? 0 : min;
	}
}


http://www.niftyadmin.cn/n/193036.html

相关文章

openGauss学习之旅——基本入手

文章目录前提准备基本概念openGauss技术指标数据库管理表管理索引管理视图管理用户管理常见数据类型前提准备 根据下面链接——安装并且可视化连接到openGauss数据库&#xff1a; https://blog.csdn.net/youngyulang/article/details/115562425 基本概念 行&#xff1a; 一行…

【Linux】编译器-gcc/g++的使用

文章目录一.背景知识二.操作前言gcc的选项1.-o 将处理结果输出到指定文件。2.预处理&#xff1a;-E 只进行预处理3.编译&#xff1a;-S 只处理到编译。4.汇编&#xff1a;-c 编译到目标代码,生成.o文件5.链接三.总结一.背景知识 gcc是由GNU开发的编程语言译器&#xff0c;GNU工…

Spring中的循环依赖是什么?如何解决它?

循环依赖是指两个或多个Bean之间相互依赖&#xff0c;导致它们无法被正确地初始化。在Spring中&#xff0c;当两个或多个Bean之间存在循环依赖时&#xff0c;Spring容器无法决定哪个Bean应该先初始化&#xff0c;因此会抛出BeanCurrentlyInCreationException异常&#xff0c;从…

Vue学习——【第四弹】

前言 上一篇文章 Vue学习——【第三弹】 中我们了解了MVVM模型&#xff0c;这篇文章接着学习Vue中的数据代理。 简单介绍 数据代理就是**一个对象(A)来代理对另一个对象(B)的属性操作(A一定要包含B)。**直接看定义大家可能觉得有些抽象&#xff0c;我们可以用代码来实现。 …

JUC并发编程高级篇第三章之CAS[Unsafe和原子增强类]

文章目录1、CAS的简介1.1、什么是CAS1.2、使用CAS的前后对比1.3、CAS如何做到不加锁的情况&#xff0c;保证数据的一致性1.4、什么是Unsafe类1.5、CAS方法参数详解1.6、CAS的原理1.7、 CAS的缺点2、原子操作类2.1、基本类型原子类2.2、数据类型原子类2.3、引用类型原子类2.4、对…

Spring Security源码剖析从入门到精通.跟学尚硅谷(一)

Spring Security源码剖析从入门到精通.跟学尚硅谷 一学习目标1. SpringSecurity 框架简介1.1 概要1.2 历史1.3 同款产品对比1.3.1 Spring Security1.3.2 Shiro1.4 模块划分2. SpringSecurity 入门案例2.1 创建一个项目(1).创建Spring Boot项目(2).更改项目依赖文件(3).添加Cont…

联想存储DE4000H重置管理口密码

联想存储DE4000H重置管理口密码1.使用串口线将pc端和存储端连接在一起&#xff0c;找到com口&#xff0c;打开putty&#xff0c;xshell等工具连接(波特率115200)&#xff1b; 2.使用SPRI’串口恢复接口’帐户登录 用户名&#xff1a;spri 密码&#xff1a;SPRlentry 一旦登…

Web 攻防之业务安全:验证码绕过测试.

Web 攻防之业务安全&#xff1a;验证码绕过测试. 业务安全是指保护业务系统免受安全威胁的措施或手段。广义的业务安全应包括业务运行的软硬件平台&#xff08;操作系统、数据库&#xff0c;中间件等&#xff09;、业务系统自身&#xff08;软件或设备&#xff09;、业务所提供…