1. 程式人生 > >給定一個整數陣列,求它的一個最長遞增子序列。

給定一個整數陣列,求它的一個最長遞增子序列。

題目描述:如題。

樣例:

    輸入 :

    5

    1 5 2 3 6 9

    輸出:

    1 2 3 6 9

分析:

    本題最好的解法是使用動態規劃,首先要想明白一個問題:如何找到以a[n]作為最後一個元素的最長子列。

    要找到以a[n]作為最後一個元素的最長子列,我們需要找出陣列中所有的a[n]之前並且比a[n]小的元素集合,設為S(a[s]), 設在S(a[s])中以元素a[s]為最後一個元素的子列為Ls(a[s]), 選擇Ls(a[s])中最長的一個加上a[n]自身就得到了以a[n]元素為隊尾的最長子列。

    要得到最終答案只需要再次遍歷陣列,比較所有以a[k](0 < k <= n)為隊末的佇列長度並選擇最長的一個即可。

Java解答:

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

import com.google.common.collect.Lists;

public class LonggestSon {
	// 輸出陣列的最長有序子序列,(子序列不要求緊緊相連)
	// 如 1 4 2 3 6 9最長子序列為:1 2 3 6 9
	
	// 演算法思路為動態規劃,下一步選擇建立在最優的上一步選擇之上。
	
	public static void main(String[] args) {
		int[] array = new int[] {};
		try {
			array = LonggestSon.getScanArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
		LonggestSon.getMaxLethSon(array);
	}

	public static int[] getScanArray() throws Exception {
		int[] result;
		Scanner scanner = new Scanner(System.in);
		int lenth = Integer.parseInt(scanner.nextLine());
		result = new int[lenth];
		String arryStr = scanner.nextLine();
		String[] arrays = arryStr.split(" ");
		if (arrays.length != lenth) {
			throw new Exception("length error");
		}
		for (int i = 0; i < lenth; i++) {
			result[i] = Integer.parseInt(arrays[i]);
		}
		return result;
	}

	public static int[] getMaxLethSon(int[] a) {
		int[] marks = new int[a.length];
		for (int i = 0; i < a.length; i++) {
			int currentMaxleth = 0;
			for (int j = 0; j < i; j++) {
				if (a[j] < a[i] && marks[j] > currentMaxleth) {
					currentMaxleth = marks[j];
				}
			}
			marks[i] = currentMaxleth + 1;
		}
		System.out.println("arrays:" + Arrays.toString(a));
		System.out.println("marks :" + Arrays.toString(marks));
		int maxleth = 0;
		int maxlethpos = 0;
		for (int i = 0; i < marks.length; i++) {
			if (marks[i] > maxleth) {
				maxleth = marks[i];
				maxlethpos = i;
			}
		}
		System.out.println("最長子序列長度 =" + maxleth);
		List<Integer> son = Lists.newArrayList();
		son.add(a[maxlethpos]);
		int currentleth = maxleth;
		for (int i = maxlethpos - 1; i >= 0; i--) {
			if (marks[i] == currentleth - 1) {
				currentleth--;
				son.add(a[i]);
			}
		}
		List<Integer> trueSon = Lists.reverse(son);
		System.out.println("最長子序列為:" + trueSon);

		return new int[] { 0 };
	}

}