LeetCode053——最大子序和

我的LeetCode代码仓:https://github.com/617076674/LeetCode

原题链接:https://leetcode-cn.com/problems/maximum-subarray/description/

题目描述:

知识点:

思路一:暴力解法(在LeetCode中提交会超时)

暴力解法的思路很简单,遍历所有可能的连续子数组,寻求其最大和。

时间复杂度是O(n ^ 3),其中n为nums数组的长度。空间复杂度是O(1)。

JAVA代码:

public class Solution {

	public int maxSubArray(int[] nums) {
		int n = nums.length;
		int result = Integer.MIN_VALUE;
        for (int i = 0; i < n; i++) {
			for (int j = i; j < n; j++) {
				int sum = 0;
				for (int k = i; k <= j; k++) {
					sum += nums[k];
				}
				result = Math.max(result, sum);
			}
		}
        return result;
    }
}

思路二:对暴力解法的改进

在思路一的最内层循环中,我们每次计算sum值时,都是从索引i一直加到索引j,事实上,计算sum时我们完全可以利用上一步的结果,即从索引i一直加到索引j可以变成从索引i一直加到索引j - 1的和再加上索引j。这就是本思路的由来。

时间复杂度是O(n ^ 2),其中n为nums数组的长度。空间复杂度为O(1)。

JAVA代码:

public class Solution {

	public int maxSubArray(int[] nums) {
		int n = nums.length;
		int result = Integer.MIN_VALUE;
        for (int i = 0; i < n; i++) {
        	int sum = 0;
			for (int j = i; j < n; j++) {
				sum += nums[j];
				result = Math.max(result, sum);
			}
		}
        return result;
    }
}

LeetCode解题报告:

思路三:分治算法

对于数组中索引在[left, right]范围内的元素,其具有最大和的连续子数组可能在左半边,也可能在右半边,也可能横跨左右两边。

递归终止条件

如果left == right,在此范围内只有一个元素,直接返回该元素的值即可。

递归过程

(1)递归调用函数求出左半边的最大和leftResult。

(2)递归调用函数求出右半边的最大和rightResult。

(3)求解横跨左右两边的最大和midResult。此时需要以mid为起点,向左和向右分别遍历数组,求出左半边最大和midLeftResult以及右半边最大和midRightResult,将这两者相加即得midResult。

时间复杂度是O(nlogn)级别的,其中n为nums数组的长度。空间复杂度即递归深度是O(logn)级别的。

JAVA代码:

public class Solution {

	public int maxSubArray(int[] nums) {
		int n = nums.length;
		int result = maxSubArray(nums, 0, n - 1);
        return result;
    }
	
	private int maxSubArray(int[] nums, int left, int right) {
		if(left == right) {
			return nums[left];
		}
		int mid = left + (right - left) / 2;
		int leftResult = maxSubArray(nums, left, mid);
		int rightResult = maxSubArray(nums, mid + 1, right);
		
		int leftSum = 0;
		int midLeftResult = Integer.MIN_VALUE;
		for (int i = mid; i >= left; i--) {
			leftSum += nums[i];
			midLeftResult = Math.max(midLeftResult, leftSum);
		}
		int rightSum = 0;
		int midRightResult = Integer.MIN_VALUE;
		for (int i = mid + 1; i <= right; i++) {
			rightSum += nums[i];
			midRightResult = Math.max(midRightResult, rightSum);
		}
		int midResult = midLeftResult + midRightResult;
		
		return Math.max(leftResult, Math.max(rightResult, midResult));
	}
}

LeetCode解题报告:

思路四:“在线算法”

对于nums中索引0 ~ n - 1,假设满足和最大的子串的左右索引分别是i和j,那么对于不论什么k(i <= k <= j),我们有nums中左右索引分别是i和k的子序列的和大于0。

因为假设存在k使得左右索引分别是i和k的子序列的和小于0。那么我们就有左右索引分别是k + 1和j的子序列的和大于左右索引分别是i和j的和,这与我们假设的array[i...j]就是array中和最大子串矛盾。

基于上述规律,我们可以一次扫描nums数组就求出具有最大和的连续子数组的最大和。关键就在于一旦出现sum < 0的情况,我们直接令sum = 0,即舍弃前面的所有的元素,从下一个元素i + 1开始计算起。因为一旦出现sum < 0的情况,说明前面的所有元素不该出现在具有最大和的连续子数组里,因为从索引i + 1开始算起肯定比算上i及到上一个起始索引之间的索引对应的nums数组的值的总和要大,因为i及到上一个起始索引之间的索引对应的nums数组的值的总和的sum < 0。

时间复杂度是O(n)级别的,其中n为nums数组的长度。空间复杂度是O(1)级别的。

JAVA代码:

public class Solution {

	public int maxSubArray(int[] nums) {
		int n = nums.length;
		int result = Integer.MIN_VALUE;
		int sum = 0;
		for (int i = 0; i < n; i++) {
			sum += nums[i];
			result = Math.max(result, sum);
			if(sum < 0) {
				sum = 0;
			}
		}
		return result;
    }
}

LeetCode解题报告:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值