【のJava / C]最大のサブ列と最大サブシーケンス合計

コース:データ構造チェン・ユエホーミング・チン


Kの整数のシーケンス所与{N 1、N 2、...、N K}。連続的なサブシーケンスは、{N I、N I + 1、...、N jを}1≤i≤j≤Kであると定義されます。最大のサブシーケンスは、その要素の最大の合計を持っている連続サブシーケンスです。例えば、{、-2、11 -4、13 -5、-2}のシーケンスを与え、その最大のサブシーケンスは、最大合計が20であると{11、-4、13}です。

今、あなたは、一緒に第一および最大サブシーケンスの最後の数字で、最大の合計を見つけることになっています。

入力仕様:

各入力ファイルには、1つのテストケースが含まれています。各ケースは2行を占めています。最初の行は、正の整数K(≤10000)を含みます。2行目は空白で区切られた、K番号を含んでいます。

出力仕様:

各テストケース1つのライン最大和に出力するため、一緒に第一及び最大サブシーケンスの最後の番号を持ちます。数字は1つのスペースで区切る必要がありますが、行の末尾に余分なスペースがあってはなりません。最大サブシーケンスは、固有、出力iとj(試料場合によって示されるように)最も小さいインデックスを有するものでない場合に。すべてのK番号が負の場合、その最大値の合計が0になるように定義され、そしてあなたが最初に全体のシーケンスの最後の番号を出力することになっています。

サンプル入力:

10
-10 1 2 3 4 -5 -23 3 7 -21

サンプル出力:

10 1 4

制限時間:200ミリ秒

メモリ制限:64メガバイト

コード:言及したオンラインカリキュラムのアプローチを使用して

import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int k = in.nextInt();//输入正整数K
		int[] nums = new int[k];
		for (int i=0; i<k; i++) {//输入K个整数
			nums[i]=in.nextInt();
		}
		in.close(); 
		
		MaxSubseqSum maxSum = new MaxSubseqSum();
		int[] result = maxSum.maxSubseqSum2(nums, k);
		for(int i=0;i<result.length;i++){//输出结果,以空格分隔
            System.out.print(result[i]);
            if(i<result.length-1){
                System.out.print(" ");
            }
        }
	}
}

class MaxSubseqSum {
	
	//在线处理法
	public int[] maxSubseqSum2(int[] a, int n){
		
		int thisSum = 0, maxSum = 0, reSum = 0;
        int first = a[0], last = a[n-1];
        int start = 0, end = 0;
        boolean flag = false;
        for(int i=0; i<n; i++){
            thisSum += a[i];
            if(thisSum > maxSum){
                maxSum = thisSum;
                end = i;
            }else if(thisSum < 0){
                thisSum = 0;
            }
            if(a[i] == 0){
                flag = true;
            }
        }
        
        for(int j=end; j>=0; j--){
            reSum += a[j];
            if(reSum == maxSum){
                start = j;
                if(a[j] >= 0) {//因为要求最大子列和不唯一时,输出的first和last值的下标要最小,故当最大子列和前面有0时,要把这些0加进来
                	continue;
                }
            }
        }

        if(maxSum > 0){
            first = a[start];
            last = a[end];
        }else if(maxSum == 0){//maxSum为0存在两种情况:一种是所有整数都为负数,此时first和last分别为输入数列的首尾值;另一种是负数和0的组合,此时无论0的位置和数量,first和last都是0,所以在上面遍历时增加flag变量以记录是否存在0
            if(flag){
                first = 0;
                last = 0;
            }
        }
        return (new int[] {maxSum,first,last});
	}
}

結果:

 最後のテストケース振れの問題が解決し、よりよい解決策を楽しみにすることができませんでした。


更新

C言語でアルゴリズムは少し、高効率動作の多くは、最後のケースは、渡されました。

#include<stdio.h>

int main(){
	int n;
	int thisSum = 0, maxSum = 0, reSum = 0;
	int start = 0, end = 0;//最大子列和首尾数字的下标 
	int first, last;//最大子列和的首尾数字 
	int flag = 0;//用来判断输入数字都是负数或零的情况 
	
	scanf("%d",&n);
	int nums[n];
	for( int i = 0; i < n; i++ ){
		scanf("%d", &nums[i]);
		thisSum += nums[i];
		if( thisSum > maxSum ){
			maxSum = thisSum;
			end = i;
		}
		else if( thisSum < 0){
			thisSum = 0;
		}
		if( nums[i] == 0 ){
			flag = 1;
		}
	}
	
	for( int j = end; j >= 0; j-- ){
		reSum += nums[j];
		if( reSum == maxSum ){
			start = j;
			if( nums[j-1] == 0 ){
				continue;
			}
		}
	}
	
	first = nums[start];
	last = nums[end]; 
	
	if( maxSum == 0 ){
		if( flag ){//输入数字是负数和零的组合 
			first = last = 0;
		}else{//输入数字都是负数 
			first = nums[0];
			last = nums[n-1];
		}
	}
	
	printf("%d %d %d", maxSum, first, last);	
    
    return 0;
}

37元記事公開 ウォン称賛47 ビューに10万+を

おすすめ

転載: blog.csdn.net/u013378642/article/details/104542554