第三周作业1(LeetCode53)

    xiaoxiao2021-03-25  72

    1. 题目描述(LeetCode53) Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

    For example, given the array [-2,1,-3,4,-1,2,1,-5,4], the contiguous subarray [4,-1,2,1] has the largest sum = 6.

    More practice: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

    2. 解决思路 这是一个非常经典的算法题,在网上搜了一篇用线性时间解决这个问题的比较详细的博客,现将博客中自己认为比较重要和难理解的证明摘录如下:

    假设使用穷举法,则至少须要O(n^2)的时间才干得到答案。卡耐基梅隆大学的Jay Kadane的给出了一个线性时间算法(时间复杂度为O(n)),我们就来看看。怎样在线性时间内解决最大子串和问题。 要说明Kadane算法的正确性,须要两个结论。 首先。对于array[1…n],假设array[i…j]就是满足和最大的子串,那么对于不论什么k(i<=k<=j),我们有array[i…k]的和大于0。因为假设存在k使得array[i…k]的和小于0。那么我们就有array[k+1…j]的和大于array[i…j],这与我们假设的array[i…j]就是array中和最大子串矛盾。

    其次,我们能够将数组从左到右切割为若干子串,使得除了最后一个子串之外,其余子串的各元素之和小于0,且对于全部子串array[i…j]和随意k(i<=k

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void MaxSubSum(int *arr, int len, int &l, int &r); int main() { int* arr = NULL; //存储数组 int len = 0; printf("请输入数组的长度:\n"); scanf("%d", &len); while (len <= 0) { printf("长度必须大于0,请重新输入:\n"); scanf("%d", &len); } arr = (int*)malloc(sizeof(int)* len); //数组分配内存 printf("请输入数组的每一位数:\n"); for (int i = 0; i<len; ++i) { scanf("%d", &arr[i]); } //调用封装好的功能函数 int l, r; MaxSubSum(arr, len, l, r); //输出结果 printf("新的数组长度为: %d\n", r - l + 1); printf("和最大的连续子数组元素为:\n"); for (int i = l; i <= r; ++i) { printf("%d ", arr[i]); } scanf("%d", &len); //加个输入让窗口停下来 free(arr); //释放内存 return 0; } void MaxSubSum(int *arr, int len, int &l, int &r) { int i; int MaxSum = 0; int CurSum = 0; int ll = -1; for (i = 0; i < len; i++) { CurSum += arr[i]; if (CurSum > MaxSum) { MaxSum = CurSum; l = ll + 1; r = i; } //如果累加和出现小于0的情况 //则和最大的子序列肯定不可能包含前面的元素 //这时累加和置零,从下个元素重新开始累加 if (CurSum <= 0) { CurSum = 0; ll = i; } } }
    转载请注明原文地址: https://ju.6miu.com/read-34978.html

    最新回复(0)