C language algorithm learning (summation of the largest sub-series)

The sum of the largest sub-series

Today, I have learned a lot about the largest continuous sub-sequence in other people’s blogs, and I will focus on repeating the two algorithms I like

1

Use the array sum[i] to represent the sum of the number from the first to the i-th, and use sum[j]-sum[i-1] to represent the sum of the number from the i-th to the jth sequence, eliminating the innermost loop , C language code is as follows:

#include <stdio.h>

//N是数组长度,num是待计算的数组,sum是数组前缀和,放在全局区是因为可以开很大的数组
int N, num[16384], sum[16384];

int main()
{
    
    
    //输入数据
    scanf("%d", &N);
    for(int i = 1; i <= N; i++)
        scanf("%d", &num[i]);
    
    //计算数组前缀和
    sum[0] = 0;
    for(int i = 1; i <= N; i++) {
    
    
        sum[i] = num[i] + sum[i - 1];
    }

    int ans = num[1]; //ans保存最大子数列和,初始化为num[1]能保证最终结果正确
    //i和j分别是枚举的子数列的起点和终点
    for(int i = 1; i <= N; i++) {
    
    
        for(int j = i; j <= N; j++) {
    
    
            int s = sum[j] - sum[i - 1];
            if(s > ans) ans = s;
        }
    }
    printf("%d\n", ans);

    return 0;
}

According to the blogger's meaning, you can also optimize it a bit, use the num array to directly save the sum instead of the sum element group:

#include <stdio.h>
int N, num[16384];

int main() {
    
    
	//输入数据
	scanf("%d", &N);
	for(int i = 1; i <= N; i++) {
    
    
		scanf("%d", &num[i]);//计算数组前缀和
		num[i] = num[i] + num[i - 1];
	}
	
	int ans = num[1]; //ans保存最大子数列和,初始化为num[1]能保证最终结果正确
	//i和j分别是枚举的子数列的起点和终点
	for(int i = 1; i <= N; i++) {
    
    
		for(int j = i; j <= N; j++) {
    
    
			int s = num[j] - num[i - 1];
			if(s > ans) ans = s;
		}
	}
	printf("%d\n", ans);

	return 0;
}

2

Divide and conquer, that is, use the recursive call of functions to solve this problem.
Use a function to divide an array into two parts with the center position as the dividing point. The answer can be divided into three cases:
1. The largest sub-number is listed on the left
2. On the right
3. Across the dividing point, each on the left and right occupies a part.
In case of 1, 2 cases, you can recurse until the third case occurs.
Deal with the third case:
1. Using the split point as the starting point, find the maximum values ​​on the left and right sides (because of the determined starting point, the complexity is not high), and add them.
The idea is so clear, then what we have to do is just to judge which situation is enough, this is not a problem, we can continue to use recursive calls to find the largest sub-sequence of 1, 2 and then compare with the maximum value on the left and right sides of the split point. can

int solve(int left,int right,int *num) {
    
    //左值,右值,数组地址 
	if(left==right) {
    
    //递归结束 
		return num[right];
	}
	int mid=right+left>>1;
	int lans =solve (right,mid,num);//Left Answer,即left max 
	int rans = solve (mid+1,left,num);//Right Answer

	int sum = 0, lmax = num[mid], rmax = num[mid + 1];
	for(int i = mid; i >= left; i--) {
    
    
		sum += num[i];
		if(sum > lmax) lmax = sum;
	}
	sum = 0;
	for(int i = mid + 1; i <= right; i++) {
    
    
		sum += num[i];
		if(sum > rmax) rmax = sum;
	}

	//答案是三种情况的最大值
	int ans = lmax + rmax;
	if(lans > ans) ans = lans;
	if(rans > ans) ans = rans;

	return ans;
}

Guess you like

Origin blog.csdn.net/seekerzhz/article/details/112976493