max sub sum II

63 篇文章 0 订阅
第一题:给一个array,给一个数字n,找出n个连续数字which和最大。

第二题:给一个array,给一个数字n,找出3个不overlap的n个连续数字使得和最大,比如说给 1 3 7 7 2 1 1 4 8 8 6 1 1 9,结果就是1 3 (7 7) 2 1 1 (4 8) (8 6) 1 1 9,输出他们的和。

import java.util.*;

public class MaxSubSumII {

	//http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=178592&extra=page%3D3%26filter%3Dsortid%26sortid%3D311%26searchoption%255B3046%255D%255Bvalue%255D%3D2%26searchoption%255B3046%255D%255Btype%255D%3Dradio&page=1
	public static void main(String[] args) {
		MaxSubSumII window = new MaxSubSumII();
        int[] nums1 = new int[] {1,3,7,7,2,1,1,4,8,8,6,1,1,9};
        int n = 2, k = 3;
        System.out.println(window.getMaxValue(nums1, n, k) == 40);
        int[] nums2 = new int[] {1,-3,7,7,-2,1,-1,4,-8,8,-6,1,1,9};
        System.out.println(window.getMaxSumKElements(nums2, 3));
}

	
	public int getMaxSumKElements(int[] nums, int k) {
		if (nums.length < k) {
			return -1;
		}
		int curMax = 0, curSum = 0;
		Queue<Integer> queue = new LinkedList<>();
		for (int i = 0; i < k; i++) {
			queue.offer(nums[i]);
			curSum += nums[i];
		}
		curMax = curSum;
		for (int i = k; i < nums.length; i++) {
			curSum = curSum - queue.poll();
			curSum = curSum + nums[i];
			queue.offer(nums[i]);
			curMax = Math.max(curSum, curMax);
		}
		return curMax;
	}
	
	
	public int getMaxValue(int[] nums, int n, int k) {
		int len = nums.length;
		int[] sum = new int[len];
		for (int i = 0; i < len; i++) {
			sum[i] = (i == 0 ? 0 : sum[i - 1]) + nums[i];
		}
		if (len <= n * k)
			return sum[len - 1];
		// ask interviewer if the method should return 0 when len < n*k
		int[] prev = new int[len + 1];
		for (int i = 1; i <= k; i++) {
			int[] dp = new int[len + 1];
			for (int j = i * n; j <= len; j++) {
				if (j == i * n)
					dp[j] = sum[j - 1];
				else
					dp[j] = Math.max(dp[j - 1], sum[j - 1] - sum[j - n - 1] + prev[j - n]);
			}
			prev = dp;
		}
		return prev[len];
	}
}


好的,我将扮演 CSDN 开发的 C知道,我会尽力回答你的问题。对于你的第一个问题,以下是我的回答: 暴力穷举法(3层循环): 我们可以使用三层循环来枚举所有可能的连续子序列,然后计算它们的和,最后找到最大的和。具体实现如下: int maxSubArraySum(int arr[], int n) { int max_sum = INT_MIN; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int sum = 0; for (int k = i; k <= j; k++) { sum += arr[k]; } if (sum > max_sum) { max_sum = sum; } } } return max_sum; } 优化穷举法(2层循环): 我们可以使用两层循环来枚举所有可能的连续子序列,然后计算它们的和,最后找到最大的和。具体实现如下: int maxSubArraySum(int arr[], int n) { int max_sum = INT_MIN; for (int i = 0; i < n; i++) { int sum = 0; for (int j = i; j < n; j++) { sum += arr[j]; if (sum > max_sum) { max_sum = sum; } } } return max_sum; } 问题转化—等效子问题求解的动态规划法(1层循环): 我们可以使用动态规划来解决这个问题,具体来说,我们定义一个数组 dp,其中 dp[i] 表示以第 i 个元素结尾的最大子序列和。然后,我们可以使用以下递推公式来计算 dp[i]: dp[i] = max(dp[i-1] + arr[i], arr[i]) 最后,我们可以遍历 dp 数组,找到其中的最大值即可。具体实现如下: int maxSubArraySum(int arr[], int n) { int max_sum = INT_MIN; int dp = arr[0]; for (int i = 1; i < n; i++) { dp = max(dp + arr[i], arr[i]); max_sum = max(max_sum, dp); } return max_sum; } 分治法(递归求解): 我们可以使用分治法来解决这个问题,具体来说,我们将数组分成两个部分,分别求出左半部分的最大子序列和、右半部分的最大子序列和以及跨越中点的最大子序列和,然后取这三个值的最大值即可。具体实现如下: int maxSubArraySum(int arr[], int l, int r) { if (l == r) { return arr[l]; } int m = (l + r) / 2; int left_max = maxSubArraySum(arr, l, m); int right_max = maxSubArraySum(arr, m+1, r); int cross_max = arr[m]; int sum = arr[m]; for (int i = m-1; i >= l; i--) { sum += arr[i]; cross_max = max(cross_max, sum); } sum = arr[m+1]; for (int i = m+2; i <= r; i++) { sum += arr[i]; cross_max = max(cross_max, sum); } return max(left_max, max(right_max, cross_max)); } int maxSubArraySum(int arr[], int n) { return maxSubArraySum(arr, 0, n-1); } 希望这些回答能够帮助你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值