「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」。
题目:给定一个整数数组nums,要求找出该整数数组中其中一个具有最大和的连续子数组,输出该最大和。
解题思路
本题的简单想法是一个个试,通过暴力解法得到所有子数组的和,返回其中最大的即可,代码只需两层for循环即可,代码如下:
public int maxSubArray(int[] nums) {
int max = Integer.MIN_VALUE;
for(int i=0;i<nums.length;i++){
int temp=0;
for(int j=i;j<nums.length;j++){
temp += nums[j];
max = Math.max(max, temp);
}
}
return max;
}
上述代码时间复杂度为,空间复杂度为。代码逻辑应该没问题,但在力扣超出时间限制,无法通过,看了一下没通过的测试数据,数据在这,够狠。。。小看着也有一万多了吧。
动态规划
利用动态规划首先需要找到动态规划的状态数组,假设记录的状态数组为dp,那么dp[i]记录的就是以第i个元素为结尾的连续子数组的最大和,dp[i]=max{dp[i-1]+nums[i], nums[i]},之后比较状态数组和最大值的大小即可得到最大子数组和,根据上述状态方程,可得下列代码:
public int maxSubArray(int[] nums) {
int max=nums[0];
int[] dp = new int[nums.length];
dp[0] = nums[0];
for(int i=1;i<nums.length;i++){
dp[i] = Math.max(dp[i-1]+nums[i], nums[i]);
max = Math.max(max, dp[i]);
}
return max;
}
上述代码运行耗时2ms,时间复杂度为,空间复杂度为。观察上述代码,可以发现我们每次只使用了状态方程的前一个状态值,而再之前的其他状态值则没有用到,此时我们可以简化代码,利用一个变量来保存前一个状态,不断更新此状态即可得到最终解,代码如下:
public int maxSubArray(int[] nums) {
int pre=nums[0], max=nums[0];
for(int i=1;i<nums.length;i++){
pre = Math.max(pre+nums[i], nums[i]);
max = Math.max(max, pre);
}
return max;
}
上述代码最终耗时1ms,时间复杂度还是,空间复杂度则变为。
最后
本题还能用分治的方法来解决,方法类似二分排序,但感觉较为繁琐,动态规划是一个很好的方法,但目前对动态规划还不是很熟。。。只能新的一年加油吧~!