最长子序列问题 最详细的解题报告

最长子序列之和问题

算法一:暴力法(时间复杂度:O(N^2))

算法描述:依次求从j到i中最大的和,并将最大的和记录在maxValue中,容易理解但是效率低。

 1 static int MaxSum1(int[] arr) {
 2         int maxValue = Integer.MIN_VALUE;
 3         for (int i = 0; i < arr.length; i++) {
 4             int curSum = 0;
 5             for (int j = 0; j <= i; j++) {
 6                 curSum += arr[j];
 7                 if (curSum > maxValue) {
 8                     maxValue = curSum;
 9                 }
10             }
11         }
12         return maxValue;
13     }

算法二:分治法(时间复杂度:O(NlogN))

算法描述:将整个序列分成两部分,序列最大和有三种情况:

1、在左边子序列中;

2、在右边子序列中;

3、一部分在做序列中,另一部分在有序列中,但是该序列一定包含左子序列的最后一个元素mid,和又子序列的第一个元素mid+1。

对于第1、2中情况,直接递归就可以了;对于第3中情况,需要从左子序列的mid出发,依次递减,求得最大值midLeftSum,再从右子序列的第一个元素mid+1出发,依次递增,求得最大值midRightSum,最后要求的值为:midLeftSum+midRightSum。

整个序列的最大和为第1、2和3中情况中的最大值。

 1 static int MaxSum2(int[] arr, int start, int end) {
 2         int maxValue = Integer.MIN_VALUE;
 3         if (start == end) {
 4             if (arr[start] > 0) {
 5                 maxValue = arr[start];
 6             }
 7         } else {
 8             int mid = (start + end) / 2;
 9             int leftMaxValue = MaxSum2(arr, start, mid);
10             int rightMaxValue = MaxSum2(arr, mid + 1, end);
11
12             int midLeftMaxValue = 0;
13             int midLeftSum = 0;
14             for (int i = mid; i >= 0; i--) {
15                 midLeftSum += arr[i];
16                 if (midLeftSum > midLeftMaxValue) {
17                     midLeftMaxValue = midLeftSum;
18                 }
19             }
20
21             int midRightMaxValue = 0;
22             int midRightSum = 0;
23             for (int i = mid + 1; i <= end; i++) {
24                 midRightSum += arr[i];
25                 if (midRightSum > midRightMaxValue) {
26                     midRightMaxValue = midRightSum;
27                 }
28             }
29             maxValue = Math.max(leftMaxValue,    Math.max(rightMaxValue, midLeftMaxValue    + midRightMaxValue));
30         }
31         return maxValue;
32     }

算法三:动态规划(时间复杂度:O(N))

算法描述:首先我们想一下,要想为最大子序列之和做贡献,该元素一定要大于0,所以如果第i个子序列之前的子序列之和小于0,就应该舍去。(我当时理解了很长时间才理解清楚)

 1 static int MaxSum3(int[] arr) {
 2         int maxValue = Integer.MIN_VALUE;
 3         int curSum = 0;
 4         for (int i = 0; i < arr.length; i++) {
 5             curSum+=arr[i];
 6             if (curSum > maxValue) {
 7                 maxValue = curSum;
 8             }
 9             if(curSum<0){ //第i以前的子序列为做出贡献,小于0,应该舍去
10                 curSum=0;
11             }
12         }
13         return maxValue;
14     }
时间: 2024-10-29 01:10:38

最长子序列问题 最详细的解题报告的相关文章

hihoCoder 1049 后序遍历 最详细的解题报告

题目来源:后序遍历 解题思路:开始时我只知道先通过先序.中序求出二叉树,然后再后序遍历二叉树,这当然也是一种解题思路,但是会做一些无用功,比如:计算二叉树.其实,可以直接通过先序序列和中序序列直接求出后序序列的.思路如下: 1.取先序序列的第一个节点为根节点: 2.在中序序列中找到根节点的下标,将中序序列分成left和right两部分: 3.根据left和right的长度计算出先序序列中的根节点的左右孩子: 4.依次递归计算出左孩子,右孩子,返回 左孩子+右孩子+根节点. 具体算法(Java版,

hihoCoder 1041 国庆出游 最详细的解题报告

题目来源:国庆出游 解题思路(下面是大神的写的): 把题目中的序列称作S,树称作T.那么对于S中的任意节点x,x的子孙节点如果在S出现的话,那么这个子孙节点的位置是有一定要求的:x的所有子孙节点在S中的位置都恰好紧跟在x的后面,没有被其他节点隔开. 设x的子孙节点是abcd,那么--xabcd--, --xbcda-- 等等是合法的,--xab-cd--, --axbcd--, --x--abcd--, 都是不合法的('-'指其他节点).对于S中每个节点都做如上判断,如果有不合法的就输出NO,如

hihoCoder 1037 数字三角形 最详细的解题报告

题目来源:hihoCoder 1037 数字三角形 解题思路:请好好看看 提示一.提示二.提示三 具体算法(java版,可以直接AC) import java.util.Scanner; public class Main { public static int[][] rewards; public static int[][] best; public static void main(String[] args) { Scanner scanner = new Scanner(System

hihoCoder 1051 补提交卡 最详细的解题报告

题目来源:补提交卡 解题思路:假设未提交程序的天数为:a1,a2,....,an,补交的张数为M.依次从a1,a2,....,an中去掉连续的 K 天(0<=K<=M),然后再来计算剩余数组中最长连续提交天数. 具体算法(Java版,直接AC) 1 import java.util.Scanner; 2 3 public class Main { 4 5 //计算数组中最长连续提交天数 6 public static int getMax(int[] array) { 7 int[] copy

hihoCoder 1052 基因工程 最详细的解题报告

题目来源:基因工程 解题思路:假设基因序列长度为N,则需要计算基因序列前K个和后K个相同所需要的最少改变次数sum. 假设基因序列为 ATACGTCT (即M=8),K=6:interval=M-K=2: 0  1  2  3  4  5  6  7 sq1    A  T  A C  G  T  C  T sq2    A  C G T   C  T 从上图可以看出,标有相同彩色的字符相同,sq1的下标为0的字符与sq2的下标为0的字符相同,即 sq1[0]==sq1[2],由此可以得出sq1

POJ 1057 File Mapping 最详细的解题报告

题目来源:POJ 1057 File Mapping 题目大意:像我的电脑那样显示文件夹和文件信息,其中在同一级目录内,文件夹排在文件的前面并且文件夹的顺序不变,同一级目录中文件按字母序排列.文件以‘f’开头,文件夹以‘d’开头,‘*’表示一个case的结束,‘#’表示所有输入内容结束. 解题思路:递归创建,最后递归输出.算法比较简单,我就不细说了,具体看代码: 具体算法(java版,可以直接运行) 1 import java.util.*; 2 3 public class Main { 4

A Broken Calculator 最详细的解题报告

题目来源:A Broken Calculator 题目如下(链接有可能无法访问): A Broken Calculator Time limit : 2sec / Stack limit : 256MB / Memory limit : 256MB Problem Dave's calculator is broken. His calculator halts when put more than K kinds of number. Dave wants to input an intege

POJ 1046 Color Me Less 最详细的解题报告

题目来源:POJ 1046 Color Me Less 题目大意:每一个颜色由R.G.B三部分组成,D=Math.sqrt(Math.pow((left.red - right.red), 2)+ Math.pow((left.green - right.green), 2)+ Math.pow((left.blue - right.blue), 2)) 表示两个不同颜色的之间的距离(以left和right为例,left和right分别为两种不同的颜色),现给出16组目标颜色,剩下的为待匹配的颜

POJ 1050 To the Max 最详细的解题报告

题目来源:To the Max 题目大意:给定一个N*N的矩阵,求该矩阵中的某一个矩形,该矩形内各元素之和最大,即最大子矩阵问题. 解题方法:最大子序列之和的扩展 解题步骤: 1.定义一个N*N的矩阵state,state[j][k]用来存放矩阵的某行中第j到k个元素的最大值: 2.对于行如何处理呢?我们可以将第一行中的N个元素的所有组合的最大值存放在state中,如果有哪个值小于0,清零,因为它没有做任何贡献:定计算第二行时与第一行的值(全部大于等于0)进行累加,这样就完成了第一行与第二行的累