【java算法實踐】一

題目

求整數數組的最大子序列和。子序列一定是連續的。

實現方式一

 

	public long fun1(Integer[] arr, int left, int right) {
		if(left == right) {
			return arr[left];
		}
		int center = (left + right)/2;
		long maxLeftSum = fun1(arr, left, center);
		long maxRightSum = fun1(arr, center+1, right);
		long maxLeftBorderSum = arr[center];
		int leftBorderSum = 0;
		for(int i=center;i>=left;i--) {
			leftBorderSum += arr[i];
			if(leftBorderSum > maxLeftBorderSum) {
				maxLeftBorderSum = leftBorderSum;
			}
		}
		long maxRightBorderSum = arr[center+1];
		int rightBorderSum = 0;
		for(int i=center+1;i<=right;i++) {
			rightBorderSum += arr[i];
			if(rightBorderSum > maxRightBorderSum) {
				maxRightBorderSum = rightBorderSum;
			}
		}
		long borderSum = maxLeftBorderSum + maxRightBorderSum;
		long max = maxLeftSum;
		if(maxRightSum > max) {
			max = maxRightSum;
		}
		if(borderSum > max) {
			max = borderSum;
		}
		return max;
	}

這裏採用了分治算法,算法的思想是分三種情況:

  • 最大子序列和出現在左半邊的子序列裏
  • 最大子序列和出現在右版本的子序列裏
  • 最大子序列和包含了左右兩邊的子序列

這個算法的時間複雜度相當於O(NlogN)。

實現方式二

	public long fun2(Integer[] arr) {
		long max = arr[0];
		long currSum = 0;
		for(int i=0;i<arr.length;i++) {
			currSum += arr[i];
			if(currSum > max) {
				max = currSum;
			}else if(currSum < 0) {
				currSum = 0;
			}
		}
		return max;
	}

這種方式比較巧妙,它只循環一次,沒有遞歸,初始最大值就是數組第一個元素,然後開始遍歷數組,每遍歷一次就累加一次,並與當前最大值進行比較以更新最大值,當出現累加值小於0,則重新置0。

這種算法的時間複雜度是O(N)。

分析

兩種實現方式從時間複雜度上來看第二種要優於第一中。而且第一種使用了遞歸,這使得它在計算時是需要將整個數組放在內存裏的,而第二種其實是不需要的,它只需要逐個讀取數組的元素即可,這樣來看,第二種算法在內存空間消耗上也比第一種好。因此,第二種算法是最優的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章