欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

最长子序列

程序员文章站 2024-02-25 08:10:52
...

最长子序列

  • C++语言编写 数组中有负数才有意义

1. 分治法

  • 采用分治方法,最大子数组的位置在中点左边,中点右边和在跨越中点。由此将整个数据求累积和分成三段,分别计算累计和。
  • 若最大子数组在段中,那么最大子数组在段的位置为中点左边,右边和跨越中点处,因此可以采用迭代算法。
  • 若在其他段同段处理。
  • 时间复杂度:设处理整个数组时间复杂度位T(n)
  • 当处理最大子数组的位置在中点左/右边时将数组分为两部分,处理这部分时时间复杂度为2*T(N/2)
  • 当处理最大子数组跨越中点时,即将左右边扫描一遍,即该部分时间复杂度为c*N
  • T(n)=2T(N/2)+cN
    =2[2T(N/2^2)+cN/2]+cN
    =…(重复k-1次)
    =2^kO(1)+ckN (取最大)
    =O(NlogN)
    //将 T(n)=2
    T(N/2)+cN 带入T(N/2) 直到找到一个k,使得N/2^k=1
//首先计算出跨越中点的段的最大值即左右下标。
//跨越中点
void FindMaxCrossingSubarray(int A[], int low, int mid, int high, int &left, int &right, int &max)
{
	int left_sum = A[mid];  //目前找到的最大值
	int sum = 0; //所有值的和
	int max_left = mid; //左边坐标
	for (int i = mid; i >= low; --i)
	{
		sum += A[i];
		if (sum > left_sum)
		{
			left_sum = sum;
			max_left = i;
		}
	}

	int right_sum = 0;  //目前找到的最大值
	sum = 0; //所有值的和
	int max_right = mid; //右边坐标

	for (int i = mid + 1; i <= high; ++i)
	{
		sum += A[i];
		if (sum > right_sum)
		{
			right_sum = sum;
			max_right = i;
		}
	}
	left = max_left;
	right = max_right;
	max = left_sum + right_sum;
}

//整个数组:
void FindMaximumSubarray(int A[], int low, int high, int &left, int &right, int &max)
{
	if (high == low)
	{
		left = low; right = high; max = A[low];
		return;
	}
	else
	{
		int left_low, left_high, left_sum;  //坐标和最大累积和
		int right_low, right_high, right_sum;
		int cross_low, cross_high, cross_sum;

		int mid = (low + high) / 2;
		FindMaximumSubarray(A, low, mid, left_low, left_high, left_sum);
		FindMaximumSubarray(A, mid + 1, high, right_low, right_high, right_sum);
		FindMaxCrossingSubarray(A, low, mid, high, cross_low, cross_high, cross_sum);
		if (left_sum >= right_sum && left_sum >= cross_sum) {
			left = left_low; right = left_high; max = left_sum;
		}
		else if (right_sum >= left_sum && right_sum >= cross_sum)
		{
			left = right_low; right = right_high; max = right_sum;
		}
		else
		{
			left = cross_low; right = cross_high; max = cross_sum;
		}
	}
}
  1. 在线处理法
  • 复杂度T(N)=O(N)
int OnlineProcessing(int A[], int N,int& start,int& end)//数组个数 开始索引 结束索引
{
	int ThisSum, MaxSum;
	int i;
	start = end = -1;
	int tmp_start = 0;
	ThisSum = 0;
	MaxSum = -1;
	for (i = 0; i < N; i++)
	{
		ThisSum += A[i];//向右累加
		if (ThisSum > MaxSum) {
			start = tmp_start;
			end = i;//
			MaxSum = ThisSum;//发现更大的和则更新当前结果
		}
		else if (ThisSum < 0)//若当前子列和为负
		{
			tmp_start =  i + 1;
			ThisSum = 0;//则不可能使得后面的部分和增大,抛弃
		}
	}
	start=start<0?0:start;
	end=end<0?0:N-1;
	return MaxSum<0?0:MaxSum;
}
相关标签: 数据结构 算法