1. 程式人生 > >最大子陣列問題(三種方式,java實現)

最大子陣列問題(三種方式,java實現)

1.動態規劃,時間複雜度為n

/**
	 * 動態規劃 : 時間複雜度n
	 * @param arr
	 * @return
	 */
	public static Integer maxSubArray(Integer[] arr) {
		Integer max_sum = Integer.MIN_VALUE;
		Integer min_index = 0;
		Integer max_index = 0;
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			if(sum < 0) {
				sum = 0;
				min_index = i;
			}
			sum = sum + arr[i];
			if(max_sum < sum) {
				max_sum = sum;
				max_index = i;
			}
		}
		System.out.print(min_index + " " + max_index + " ");
		return max_sum;
	}

2.暴力求解,時間複雜度為n^2
/**
	 * 暴力求解 : 時間複雜度n^2
	 * @param arr
	 * @return
	 */
	public static Integer maxSubArray(Integer[] arr) {
		Integer max_sum = Integer.MIN_VALUE;
		Integer min_index = 0;
		Integer max_index = 0;
		for (int i = 0; i < arr.length; i++) {
			int sum = 0;
			for (int j = i; j < arr.length; j++) {
				sum += arr[j];
				if(sum > max_sum) {
					min_index = i;
					max_index = j;
					max_sum = sum;
				}
			}
		}
		System.out.print(min_index + " " + max_index + " ");
		return max_sum;
	}
3.遞迴,時間複雜度為n*logn
/**
	 * 遞迴演算法 : 將陣列一分為2,最大子陣列要麼在左邊部分;要麼在右邊部分;要麼穿過中點,最邊一部分+右邊一部分。 時間複雜度:n*logn
	 * @return 結果陣列:起點,終點,最大值
	 */
	public static Integer[] find_maximum_subarray(Integer[] A, int low, int high) {
		if(high == low) {
			return new Integer[]{low, high, A[low]};
		} else {
			int mid = (low + high) / 2;
			Integer[] l_maximum_subarray = find_maximum_subarray(A, low, mid);
			Integer[] r_maximum_subarray = find_maximum_subarray(A, mid + 1, high);
			Integer[] crossing_subarray = find_max_crossing_subarray(A, low, mid, high);
			if(l_maximum_subarray[2] >= r_maximum_subarray[2] && l_maximum_subarray[2] >= crossing_subarray[2]) {
				return l_maximum_subarray;
			} else if(r_maximum_subarray[2] >= l_maximum_subarray[2] && r_maximum_subarray[2] >= crossing_subarray[2]) {
				return r_maximum_subarray;
			} else {
				return crossing_subarray;
			}
		}
	}
	
	public static Integer[] find_max_crossing_subarray(Integer[] A, int low, int mid, int high) {
		int left_sum = Integer.MIN_VALUE;
		int sum = 0;
		int max_left = 0;
		for (int i = mid; i >= low; i--) {
			sum = sum + A[i];
			if(sum > left_sum) {
				left_sum = sum;
				max_left = i;
			}
		}
		int right_sum = Integer.MIN_VALUE;
		int max_right = 0;
		sum = 0;
		for (int j = mid + 1; j <= high; j++) {
			sum = sum + A[j];
			if(sum > right_sum) {
				right_sum = sum;
				max_right = j;
			}
		}
		return new Integer[]{max_left, max_right, left_sum + right_sum};
	}