求解向量中连续子向量的最大和

开篇

本篇文章旨在求解向量中n个连续子向量的最大和。题目来源是《编程珠玑》第8章《算法设计技术》。

问题描述

输入:具有n个浮点数的向量x;

输出:输入向量的任何连续子向量中的最大和;

例如:输入向量为31,-41,59,26,-53,58,97,-93,-23,84;

那么输出就是从59到97五个数的总和,即:187.

代码实现

简单算法--时间复杂度: O(n^3)

c 复制代码
#include <stdio.h>

#define Max(a,b)((a)>(b)?(a):(b))

int main() {
	int nums[10] = { 31,-41,59,26,-53,58,97,-93,-23,84 };

	// 定义连续向量最大值
	int maxsofar = 0;
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			int sum = 0;
			for (int k = i; k <= j; k++) {
				sum += nums[k];
			}
			maxsofar = Max(maxsofar, sum);
		}
	}

	printf("最大值为%d.\n", maxsofar);
	return 0;
}

两个平方算法之一--时间复杂度O(n^2)

c 复制代码
// 平方算法1---时间复杂度O(n^2)
int maxSubArraySumPro(int *nums, int length) {
	int maxsofar = 0;
	for (int i = 0; i < length;  i++) {
		int sum = 0;
		for (int j = i; j < length; j++) {
			sum += nums[j];
			maxsofar = Max(maxsofar, sum);
		}
	}

	return maxsofar;
}

两个平方算法之二--时间复杂度O(n^2)

c 复制代码
// 平方算法2 --- 时间复杂度O(n^2)
int maxSubArraySumProPlus(int *nums, int length) {
	int len = length + 1;

	// 动态分配数组的内存
	int *cumarr = (int *)malloc(len * sizeof(int));

	if (cumarr == NULL) {
		printf("内存分配失败!\n");
		return -1;
	}

	cumarr[0] = 0;
	for (int i = 1; i < len; i++) {
		cumarr[i] = cumarr[i - 1] + nums[i - 1];
	}

	int maxsofar = nums[0];
	for (int i = 0; i < length; i++) {
		for (int j = i; j < length; j++) {
			int sum = cumarr[j+1] - cumarr[i];
			maxsofar = Max(maxsofar, sum);
		}
	}

	free(cumarr);
	return maxsofar;
}

分治算法--时间复杂度:O(logn)

c 复制代码
// 分治算法实现 --- 时间复杂度O(logn)
int dnc(int l, int u, int *nums) {
	if (l > u) { // 0元素数组
		return 0;
	}
	if (l == u) { // 1元素数组
		return Max(0, nums[l]);
	}

	int m = (l + u) / 2;
	int lmax = 0; // 左边最大连续数组的和
	int lsum = 0;
	for (int i = m; i >= l; i--) {
		lsum += nums[i];
		lmax = Max(lmax, lsum);
	}

	int rmax = 0;
	int rsum = 0;
	for (int i = m + 1; i <= u; i++) {
		rsum += nums[i];
		rmax = Max(rmax, rsum);
	}

	return MaxT(lmax + rmax, dnc(l, m, nums), dnc(m + 1, u, nums));
}

Kadane's算法实现--时间复杂度:O(n)

c 复制代码
// Kadane's算法实现 --- 时间复杂度O(n)
int maxSubArraySumKadane(int* nums, int length) {
	int maxsofar = nums[0];  // 初始化最大子数组和为数组的第一个元素
	int currmax = nums[0];   // 当前子数组和初始化为数组的第一个元素

	// 从第二个元素开始遍历数组
	for (int i = 1; i < length; i++) {
		// 当前子数组和为当前位置的元素与之前子数组和的和,如果当前元素本身更大,则重新开始一个子数组
		currmax = (nums[i] > currmax + nums[i]) ? nums[i] : currmax + nums[i];

		// 更新最大子数组和
		maxsofar = (currmax > maxsofar) ? currmax : maxsofar;
	}

	return maxsofar;
}

代码总集

c 复制代码
#include <stdio.h>
#include <stdlib.h>

#define Max(a,b)((a)>(b)?(a):(b))

// 辅助函数:返回三个数中的最大值
int MaxT(int a, int b, int c) {
	int maxab = (a > b) ? a : b;
	return (maxab > c) ? maxab : c;
}


// 简单算法--时间复杂度O(n^3)
int maxSubArraySum(int nums[], int length) {
	// 定义连续向量最大值
	int maxsofar = 0;
	for (int i = 0; i < length; i++) {
		for (int j = 0; j < length; j++) {
			int sum = 0;
			for (int k = i; k <= j; k++) {
				sum += nums[k];
			}
			maxsofar = Max(maxsofar, sum);
		}
	}

	return maxsofar;
}

// 平方算法1---时间复杂度O(n^2)
int maxSubArraySumPro(int *nums, int length) {
	int maxsofar = 0;
	for (int i = 0; i < length;  i++) {
		int sum = 0;
		for (int j = i; j < length; j++) {
			sum += nums[j];
			maxsofar = Max(maxsofar, sum);
		}
	}

	return maxsofar;
}

// 平方算法2 --- 时间复杂度O(n^2)
int maxSubArraySumProPlus(int *nums, int length) {
	int len = length + 1;

	// 动态分配数组的内存
	int *cumarr = (int *)malloc(len * sizeof(int));

	if (cumarr == NULL) {
		printf("内存分配失败!\n");
		return -1;
	}

	cumarr[0] = 0;
	for (int i = 1; i < len; i++) {
		cumarr[i] = cumarr[i - 1] + nums[i - 1];
	}

	int maxsofar = nums[0];
	for (int i = 0; i < length; i++) {
		for (int j = i; j < length; j++) {
			int sum = cumarr[j+1] - cumarr[i];
			maxsofar = Max(maxsofar, sum);
		}
	}

	free(cumarr);
	return maxsofar;
}

// Kadane's算法实现 --- 时间复杂度O(n)
int maxSubArraySumKadane(int* nums, int length) {
	int maxsofar = nums[0];  // 初始化最大子数组和为数组的第一个元素
	int currmax = nums[0];   // 当前子数组和初始化为数组的第一个元素

	// 从第二个元素开始遍历数组
	for (int i = 1; i < length; i++) {
		// 当前子数组和为当前位置的元素与之前子数组和的和,如果当前元素本身更大,则重新开始一个子数组
		currmax = Max(nums[i], currmax + nums[i]);

		// 更新最大子数组和
		maxsofar = Max(currmax, maxsofar);
	}

	return maxsofar;
}

// 分治算法实现 --- 时间复杂度O(logn)
int dnc(int l, int u, int *nums) {
	if (l > u) { // 0元素数组
		return 0;
	}
	if (l == u) { // 1元素数组
		return Max(0, nums[l]);
	}

	int m = (l + u) / 2;
	int lmax = 0; // 左边最大连续数组的和
	int lsum = 0;
	for (int i = m; i >= l; i--) {
		lsum += nums[i];
		lmax = Max(lmax, lsum);
	}

	int rmax = 0;
	int rsum = 0;
	for (int i = m + 1; i <= u; i++) {
		rsum += nums[i];
		rmax = Max(rmax, rsum);
	}

	return MaxT(lmax + rmax, dnc(l, m, nums), dnc(m + 1, u, nums));
}

int main() {
	int nums[10] = { 31,-41,59,26,-53,58,97,-93,-23,84 };

	int maxSum = maxSubArraySumKadane(nums, 10);
	// int maxSum = dnc(0, 9, nums);

	printf("最大值为%d.\n", maxSum);
	return 0;
}

上面的代码总体来说比较简单,此处就不过多解释了。值得一提的是,题目中要求的是浮点型,而我用的是int类型,这个是我实现的过程中的疏漏,还请谅解了。

希望本文对您能有所帮助,感谢阅读。

相关推荐
a31582380611 分钟前
大语言模型应用开发技术要求
算法·大语言模型·应用开发
倦王13 分钟前
力扣日刷26112
算法·leetcode·职场和发展
liu****23 分钟前
能源之星案例
人工智能·python·算法·机器学习·能源
CCPC不拿奖不改名31 分钟前
数据处理与分析:pandas基础+面试习题
开发语言·数据结构·python·面试·职场和发展·pandas
2501_9011478334 分钟前
环形房屋打家劫舍算法
考研·算法·leetcode·高考
智驱力人工智能42 分钟前
守护矿山动脉 矿山皮带跑偏AI识别系统的工程化实践与价值 皮带偏离检测 皮带状态异常检测 多模态皮带偏离监测系统
大数据·人工智能·opencv·算法·安全·yolo·边缘计算
智驱力人工智能1 小时前
构筑安全红线 发电站旋转设备停机合规监测的视觉分析技术与应用 旋转设备停机检测 旋转设备异常检测 设备停机AI行为建模
人工智能·opencv·算法·安全·目标检测·计算机视觉·边缘计算
宵时待雨1 小时前
数据结构(初阶)笔记归纳2:顺序表的实现
c语言·数据结构·笔记·算法
寻星探路1 小时前
【算法进阶】滑动窗口与前缀和:从“和为 K”到“最小覆盖子串”的极限挑战
java·开发语言·c++·人工智能·python·算法·ai
不穿格子的程序员1 小时前
从零开始刷算法——二叉树篇:层序遍历 + 有序数组转二叉搜索树
算法