JAVA
① 贪心 + 动态规划一(2ms)
import java.util.Arrays;
class Solution {
public int maxSubArray(int[] nums) {
int len = nums.length;
for (int i = 1; i < len; ++i) {
if (nums[i - 1] > 0) // 若数组前一个位置的值大于 0,则叠加到这个位置上
nums[i] += nums[i - 1];
}
Arrays.sort(nums);
return nums[len - 1]; // 返回最大值
}
}
② 贪心 + 动态规划二(0ms)
class Solution {
public int maxSubArray(int[] nums) {
int ans = nums[0], tmp = nums[0];
int len = nums.length;
for (int i = 1; i < len; ++i) {
tmp = Math.max(nums[i], tmp + nums[i]); //也可以理解成只有数组前一个位置的值大于 0 才取叠加值
ans = Math.max(ans, tmp);
}
return ans;
}
}
③ 分治(1ms)【时间复杂度: O ( N l o g N ) O(NlogN) O(NlogN) 空间复杂度: O ( l o g N ) O(logN) O(logN)】
class Solution {
public class Status {
public int lSum, rSum, mSum, iSum; // 记得设置 public
public Status(int lSum, int rSum, int mSum, int iSum) {
this.lSum = lSum;
this.rSum = rSum;
this.mSum = mSum;
this.iSum = iSum;
}
}
public Status getInfo(int[] a, int l, int r) { // 返回类型是类
if (l == r) {
return new Status(a[l], a[l], a[l], a[l]);
}
int m = (l + r) >> 1;
Status lSub = getInfo(a, l, m);
Status rSub = getInfo(a, m + 1, r);
return pushUp(lSub, rSub); // 返回函数类型直接是类
}
public Status pushUp(Status l, Status r) { // 返回类型是类
int iSum = l.iSum + r.iSum;
int lSum = Math.max(l.lSum, l.iSum + r.lSum);
int rSum = Math.max(r.rSum, r.iSum + l.rSum);
int mSum = Math.max(Math.max(l.mSum, r.mSum), l.rSum + r.lSum);
return new Status(lSum, rSum, mSum, iSum);
}
public int maxSubArray(int[] nums) {
return getInfo(nums, 0, nums.length - 1).mSum; // 返回类型是结构体的整型变量
}
}
据说线段树的思想就是分治,那这真是出了道好题
本代码使用了类,相当于C++使用了结构体,下面两个函数并不是类的继承,而是返回值为类的普通函数,之所以要用到类,是因为对每个区间都要记录它的四个变量,并放在类中
简单来说,最大序列要么是左边区间的最大值,要么是右边区间的最大值,要么是左边区间以右端点为区间的最大值+右边区间以左端点为区间的最大值,三者中取最大值,如此递归下去,直至区间的左端点等于右端点(区间只有一个元素)
Python
① 贪心 + 动态规划(48ms)
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
for i in range(1,len(nums)):
nums[i] = max(nums[i-1]+nums[i],nums[i])
return max(nums)
② 分治(132ms)
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
# 递归终止条件
if n == 1:
return nums[0]
else:
# 递归计算左半边最大子序和
max_left = self.maxSubArray(nums[0:len(nums) // 2])
# 递归计算右半边最大子序和
max_right = self.maxSubArray(nums[len(nums) // 2:len(nums)])
# 计算中间的最大子序和,从右到左计算左边的最大子序和,从左到右计算右边的最大子序和,再相加
max_l = nums[len(nums) // 2 - 1]
tmp = 0
for i in range(len(nums) // 2 - 1, -1, -1):
tmp += nums[i]
max_l = max(tmp, max_l)
max_r = nums[len(nums) // 2]
tmp = 0
for i in range(len(nums) // 2, len(nums)):
tmp += nums[i]
max_r = max(tmp, max_r)
# 返回三个中的最大值
return max(max_right, max_left, max_l+max_r)
相比于 J A V A JAVA JAVA 的传递类,直接传递 n u m s nums nums 数组是个非常妙的操作
演示一下列表的切片
a=[1,2,3]
print(a[0 : len(a)//2]) # a[0:1]
print(a[len(a)//2 : len(a)]) # a[1:2]
output:
[1]
[2,3]