最大子数组问题(三种方式,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};
	}

点赞