方法1:
class Solution {
public int maxSubArray(int[] nums) {
int sum=0;
int now=nums[0];
for(int i=0;i<nums.length;i++){
if(sum<0){
sum=nums[i];
}else{
sum+=nums[i];
}
now=Math.max(sum,now);
}
return now;
}
}
动态规划有点蒙了,给我搞的有点转向,养足精神再看
补2019-10-26 星期六 组合数学逃了。。
class Solution {
public int maxSubArray(int[] nums) {
int max=Integer.MIN_VALUE;
int cur=0;
for(int i=0;i<nums.length;i++){
max=Math.max(max,nums[i]+cur);
cur=cur+nums[i];
if(cur<0){
cur=0;
}
}
return max;
}
}
扩充:找到不相容的两个子数组的最大累加和
分析:数组的预处理技巧+上面的求累加和
第一个预处理数组放0-n(n=0,1,2,3,4,…)的最大累加和,第二个数组是从n-末尾的最大累加和,下面代码缺了一个遍历对比操作,就是从1个数组拿和第二个数组拿,去找最大值,就遍历一次就行,很简单
package orc.shi.s;
public class TreeNode {
public static void main(String[] args) {
int[] arr= {5,4,3,2,1,6};
int max=Integer.MIN_VALUE;
//初始化第一个预处理数组
int cur=0;//表示之前的累加和=0
int[] arr1=new int[arr.length];
for(int i=0;i<arr.length;i++) {
cur=cur+arr[i];
max=Math.max(cur, max);
if(cur<0) {
cur=0;
}
arr1[i]=max;
}
//初始化第二个预处理数组
cur=0;
max=Integer.MIN_VALUE;
int[] arr2=new int[arr.length];
for(int j=arr.length-1;j>=0;j--) {
cur=cur+arr[j];
max=Math.max(cur, max);
arr2[j]=max;
if(cur<0) {
cur=0;
}
}
System.out.println("打印第一个数组:");
dayin(arr1);
System.out.println("打印第二个数组");
dayin(arr2);
System.out.println("结束");
}
public static void dayin(int[] arr) {
for(int i:arr) {
System.out.println(i);
}
}
}
扩充题:
分析一下,我们都知道一个矩阵给你了,他的子矩阵的数量是o(n^4),因为两个顶点可以确定一个矩阵,每个顶点的选择是 n^2,但是我们不这么做,我们也是遍历所有的可能性,但是我们是按着一定的顺序来的,如:1行,1-2行,1-3。。。2行,2-2。。。这样,这样就可以用到子序列求和,秒,时间复杂度 o(n^3)
package orc.shi.s;
public class TreeNode {
public static void main(String[] args) {
int[][] arr = { { -90, 48, 78 }, { 64, -40, 64 }, { -81, -7, 66 } };
int max=Integer.MIN_VALUE;
for(int i=0;i<arr.length;i++) {
//初始化压缩数组
int[] temp=new int[arr[0].length] ;
for(int j=i;j<arr.length;j++) {
int cur=0;//这个也要注意,必须放在这,因为每一次重新计算一个行的累加和的时候cur都必须重置0;
for(int k=0;k<arr[0].length;k++) {
temp[k]=temp[k]+arr[j][k];
}
//计算最大累加和
for(int k=0;k<arr[0].length;k++) {
cur=cur+temp[k];
max=Math.max(cur, max);
if(cur<0) {
cur=0;
}
}
}
}
System.out.println(max);
System.out.println("标准版");
System.out.println(maxSum(arr));
}
public static int maxSum(int[][] m) {
if (m == null || m.length == 0 || m[0].length == 0) {
return 0;
}
int max = Integer.MIN_VALUE;
int cur = 0;
int[] s = null;
for (int i = 0; i != m.length; i++) {
s = new int[m[0].length];
for (int j = i; j != m.length; j++) {
cur = 0;
for (int k = 0; k != s.length; k++) {
s[k] += m[j][k];
cur += s[k];
max = Math.max(max, cur);
cur = cur < 0 ? 0 : cur;
}
}
}
return max;
}
}
Leetcode 1074:元素为目标值的子矩阵数量
本来我是想做上面的1074的,但是太难了。。还是不会,这时候我看到个leetcode523,我感觉可以从这个题去想1074怎么做,所以补一个
Leetcode523:连续的子数组和
题目
这里引一篇大佬的文章:保存数组前缀
class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
//对某个数取余数得到的m,表示这个数含m,所以下次需要m时候可以从减去这个数,这是这个题的原理
int subsum=0;
Map<Integer,Integer> map=new HashMap();
map.put(0,-1);//记住0是特殊的,因为如果一个数余数是0,那么不该把他不算(如果是其他,是不算的,因为是吧他减去,但是对于0是算的,对于0,0这种也是满足上面的,他这个直接赋值-1,就是表示只要遇到余数为0的,且不是第一个位置就true,第一个位置为0的话是不行的0--1=1)
for(int i=0;i<nums.length;i++){
subsum+=nums[i];
int temp=subsum;
if(k!=0){
temp=subsum%k;
}
if(map.containsKey(temp))
{
if((i-map.get(temp))>1){
return true;
}
}else{
map.put(temp,i);
}
}
return false;
}
}
Leetcode 1074:元素为目标值的子矩阵数量,看不懂答案 ,以后做