长度最小的子数组(暴力解法 + 滑动窗口)

目录

前言

一、暴力解法

二、滑动窗口



前言

题目描述:给定一个含有 n 个正整数的数组和一个正整数 target。找出该数组中满足其和 >= target 的长度最小的连续子数组 [nums_l, nums_l+1, ..., nums_r-1, nums_r],并返回其长度。如果不存在符合条件的子数组,返回 0。

题目链接209. 长度最小的子数组 - 力扣(Leetcode)

一、暴力解法

#include <limits.h>

int minSubArrayLen(int target, int* nums, int numsSize)
{
	int i = 0;
	int j = 0;
	int sum = 0;
	int subLength = 0;
	int result = INT_MAX;  // 或者 int result = numsSize + 1;
	for (i = 0; i < numsSize; i++)  // 子数组的起点为 i
	{
		sum = 0;  // 子数组的元素和
		for (j = i; j < numsSize; j++)  // 子数组的终点为 j
		{
			sum += nums[j];
			if (sum >= target)
			{
				subLength = j - i + 1;  // 求满足条件的子数组的长度
				result = subLength < result ? subLength : result;  // 求较小值
				break;  // 退出内层循环
			}
		}
	}
	return result == INT_MAX ? 0 : result;
}

二、滑动窗口

滑动窗口算法思想是非常重要的一种思想,可以用来解决数组、字符串的子元素问题。它可以将嵌套循环的问题,转换为单层循环问题,降低时间复杂度,提高效率。

算法思路

  1. 使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个窗口

  2. 先不断地增加 right 指针,扩大窗口 [left, right],直到窗口符合要求

  3. 停止增加 right,转而不断增加 left 指针,缩小窗口 [left, right],直到窗口中的子数组(或子字符串)不再符合要求。同时,每次增加 left,我们都要更新一轮结果。

  4. 重复第 2 和第 3 步,直到 right 到达尽头

int minSubArrayLen(int target, int* nums, int numsSize)
{
	int left = 0;
	int right = 0;
	int sum = 0;
	int subLength = 0;
	int result = numsSize + 1;
	for (right = 0; right < numsSize; right++)
	{
		sum += nums[right];
		while (sum >= target)  // 不断地增加 right 指针,扩大窗口 [left, right],直到窗口符合要求
		{
			subLength = right - left + 1;
			result = subLength < result ? subLength : result;
			sum -= nums[left++];  // 不断地增加 left 指针,缩小窗口 [left, right],直到窗口不符合要求
		}
	}
	return result <= numsSize ? result : 0;
}

示例:

输入:target = 7,nums = {2, 3, 1, 2, 4, 3}
输出:2

 过程如下图所示:

left = 0 时的最优解为 right = 3;

left 为 1 时的最优解为 right = 4;

left 为 2 时的最优解为 right = 4;

left 为 3 时的最优解为 right = 5;

left 为 4 时的最优解为 right = 5;

left 为 5 时没有解。 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
最小循环数组是指在一个循环数组中,找到一个连续数组,使该数组的和最小。对于解决这个问题,可以使用Java编程语言来实现。 首先,我们需要定义一个函数来计算数组的和。该函数的输入参数为一个整数数组,返回值为数组的总和。下面是该函数的Java代码实现: ```java public int getSum(int[] nums) { int sum = 0; for (int num : nums) { sum += num; } return sum; } ``` 接下来,我们可以编写一个函数来找到最小循环数组的和。该函数的输入参数为一个整数数组,返回值为最小循环数组的和。下面是该函数的Java代码实现: ```java public int findMinSubarraySum(int[] nums) { int sum = getSum(nums); int currentSum = 0; int minSum = sum; for (int i = 0; i < nums.length; i++) { currentSum += nums[i]; if (currentSum > sum) { currentSum = nums[i]; } minSum = Math.min(minSum, currentSum); } return minSum; } ``` 在这段代码中,我们使用了一个变量currentSum来记录当前数组的和,另一个变量minSum来记录最小循环数组的和。在遍历数组过程中,如果当前数组的和大于整个数组的总和,就将currentSum重置为当前元素的值。每次更新minSum时,都使用Math.min函数来比较两个和的大小,并将较小的值赋给minSum。 最后,我们可以调用findMinSubarraySum函数来找到最小循环数组的和。下面是一个例: ```java int[] nums = {4, 3, -2, -1, -3, 4, 5}; int minSubarraySum = findMinSubarraySum(nums); System.out.println("最小循环数组的和为:" + minSubarraySum); ``` 以上就是最小循环数组问题的Java解法,通过以上的代码实现,可以计算出最小循环数组的和。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值