1. 程式人生 > >【演算法設計與分析】6、最大欄位和

【演算法設計與分析】6、最大欄位和

/**
* 書本:《演算法分析與設計》
* 功能:若給定n個整陣列成的序列a1, a2, a3, ......an, 求該序列形如ai+a(i+1)+......+an的最大值
* 檔案:MaxSum.cpp
* 時間:2014年11月30日17:37:26
* 作者:cutter_point
*/

#include <iostream>

using namespace std;

//方法一:
/*
簡單的解決方式時間複雜度是O(n^3)
解決方法就是一般演算法
*/
//給我一串數字元素,找到最大的欄位和的那個欄位
//n是這串數字的個數, a是這串數字, besti是最佳的開始加的位置,bestj是最佳的結束位置
int MaxSum(int n, int *a, int& besti, int& bestj)
{
	int sum = 0;	//統計得到的最大值,從中選出最大的
	for (int i = 1; i <= n; ++i)	//從第一個數字開始,到最後一個數
	{
		for (int j = i; j <= n; ++j)	//j是表明要在i開始到j的累加範圍
		{
			int thissum = 0;	//一這個i起始的開始向後加到j的當前這個i之後對應的最大欄位和
			//開始從i開始往後一個一個的加,並把選到最大的那個欄位和
			for (int k = i; k <= j; ++k)	//重這個i加到j(j這個值每個都會試到)
				thissum += a[k];

			if (thissum > sum)
			{
				sum = thissum;	//把新的最大值放給要返回的值
				besti = i;	//最好的起始位置給記住
				bestj = j;	//最好的結束位置給記住
			}

		}
	}

	return sum;	//返回最大值
}


//方法二:
/*
簡單的解決方式時間複雜度是O(n^2)
解決方法就是運用一個數學公式i到j的累加 = 第j個數 + 前面的j-1個和
*/
//給我一串數字元素,找到最大的欄位和的那個欄位
//n是這串數字的個數, a是這串數字, besti是最佳的開始加的位置,bestj是最佳的結束位置
int MaxSum2(int n, int *a, int& besti, int& bestj)
{
	int sum = 0;	//還是這個是得到最終的結果
	//還是從第i個開始向後加j,知道所有的i都得到比較
	for (int i = 1; i <= n; ++i)
	{
		//這個i對應的最大值是
		int thissum = 0;
		for (int j = i; j <= n; ++j)
		{
			thissum += a[j];	//從i開始累加
			if (thissum > sum)	//只要找到比上一個的sum大的就代入
			{
				sum = thissum;
				besti = i;
				bestj = j;
			}
		}

	}

	return sum;
}


//方法三:
/*
簡單的解決方式時間複雜度是O(nlogn)
解決方法就是運用分治遞迴的方式
就是最優子結構是

a[1:n]的最大欄位是a[1:n/2]相同的
a[1:n]的最大欄位是a[n/2+1:n]相同的
a[1:n]的最大欄位和為i到j的累加,且i和j分別在中點的兩端

*/
//給我一串數字元素,找到最大的欄位和的那個欄位
//a裡面是這一串數字,left是這串數字的開始位置,right是這串數字的結束位置
int MaxSubSum(int *a, int left, int right)
{
	int sum = 0; //還是用來計數最大值
	//如果只有一個數了,那麼就開是比0大還是比0小,大就是這個數了,小那麼還是不用加了就等於0把
	if (left == right)	//還有這一步是為了方便遞迴
		sum = a[left] > 0 ? a[left] : 0;
	else	//如果不止一個數的話
	{
		int center = (left + right) / 2;
		//1、得到左邊的最大值
		int leftsum = MaxSubSum(a, left, center);
		//2、得到右邊的最大值
		int rightsum = MaxSubSum(a, center + 1, right);

		//3、如果左邊和右邊夾在一起合成的欄位和的話
		//用一個數來表示左邊正數的和
		int s1 = 0;	//從右到左得到最大的那個值
		int lefts = 0;	//依次加上左邊的下一個值得和
		for (int i = center; i >= left; --i)	//從中間向左邊疊加,為何和右邊的合併所以必須這樣加
		{
			lefts += a[i];	//依次加到lefts裡面
			if (lefts > s1)
				s1 = lefts;	//如果這個加起來的和,從右到左得到最大的那個值
		}

		//右邊同上
		int s2 = 0; //從左到右得到最大的那個值
		int rights = 0; //依次加上右邊的下一個值得和
		for (int i = center + 1; i <= right; ++i) //從中間向右邊疊加,為何和左邊的合併所以必須這樣加
		{
			rights += a[i]; //依次加到lefts裡面
			if (rights > s2)
				s2 = rights;
		}

		//第三種方式的和是
		sum = s1 + s2;

		//比較三種方式的大小,選出最大的那個
		if (sum < leftsum) sum = leftsum;
		if (sum < rightsum) sum = rightsum;
	}

	return sum;
}

//迭代結束之後得到最大值的方式
//n是數字的個數,a是這串數字的長度
int MaxSum3(int n, int *a)
{
	return MaxSubSum(a, 1, n);
}

int main()
{
	int a[] = { 0, -1, 7, -3, -3, 5, -2, 7 };
	//得到陣列的長度
	int n = sizeof(a) / sizeof(*a)-1;
	int besti = 0, bestj = 0;

	cout << "這串數字是:" << endl;
	for (int i = 1; i <= n; ++i)
		cout << a[i] << " ";

	cout << endl;

	cout << "最長欄位和是:" << MaxSum(n, a, besti, bestj);
	cout<< " 從" << besti << "到" << bestj << endl;
	cout << "最長欄位和是:" << MaxSum2(n, a, besti, bestj);
	cout << " 從" << besti << "到" << bestj << endl;
	cout << "最長欄位和是:" << MaxSum3(n, a)<<endl;

	return 0;
}




相關推薦

演算法設計分析6

/** * 書本:《演算法分析與設計》 * 功能:若給定n個整陣列成的序列a1, a2, a3, ......an, 求該序列形如ai+a(i+1)+......+an的最大值 * 檔案:MaxSum.cpp * 時間:2014年11月30日17:37:26 * 作者:cu

演算法設計分析貪心策略——最佳郵局設定問題

//總是感覺生活很空虛,就只能寫寫部落格看看書上上課這樣子。想出去,去一個遙遠的地方。先來看一下題目:有n戶人家坐落在從西向東的一條街上。從街西頭向東數,第i戶的房子與街西頭的距離是H[i]米,(1≤i≤n), H[1]< H[2] < H[3] … < H

計算機演算法設計分析——SVM

一.簡介 支援向量機(support vector machines)是一種二分類模型,它的目的是尋找一個超平面來對樣本進行分割,分割的原則是間隔最大化,最終轉化為一個凸二次規劃問題來求解。由簡至繁的模型包括: (1)當訓練樣本線性可分時,通過硬間隔最大化,學習一個線性可分支援向量機;(2)當訓練樣本近似

演算法設計分析作業題第十一週:20. Valid Parentheses

題目 C++ solution class Solution { public: bool isValid(string s) { stack<char> cstack; for (int i = 0; i < s.si

計算機演算法設計分析——NP

  時間複雜度 時間複雜度並不是表示一個程式解決問題需要花多少時間,而是當問題規模擴大後,程式需要的時間長度增長得有多快。也就是說,對於高速處理資料的計算機來說,處理某一個特定資料的效率不能衡量一個程式的好壞,而應該看當這個資料的規模變大到數百倍後,程式執行時間是否還是一樣,或者也跟著慢了數百倍

演算法設計分析作業題第二週:1. Two Sum

題目 C++ solution class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { ve

演算法設計分析作業題第九周:17. Letter Combinations of a Phone Number

題目 C++ solution class Solution { public: vector<string> letterCombinations(string digits) { vector<string>

歸併排序快速排序比較演算法設計分析實驗報告

       下面的原始碼是修改的了時間差精確到了納秒級別的了,但是還是感覺很有誤差。無論怎麼測,總是快排比歸併快,即使是測試資料的陣列長度在10以內。         前面一樣的程式寫的是時間精確到微秒級的,陣列長度大概在一萬以內的,就是歸併排序快了,大於這個長度的快速排

演算法設計分析作業題第十週:19. Remove Nth Node From End of List

題目 C++ solution /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListN

『嗨威說』演算法設計分析 - PTA 數字三角形 / 大子段 / 編輯距離問題(第三章上機實踐報告)

本文索引目錄: 一、PTA實驗報告題1 : 數字三角形   1.1  實踐題目   1.2  問題描述   1.3  演算法描述   1.4  演算法時間及空間複雜度分析 二、PTA實驗報告題2 : 最大子段和   2.1  實踐題目   2.2  問題描述   2.

MySQL 線上 BUG 分析之 多表同異常:Column ‘xxx’ in field list is ambiguous

一、生產出錯! 今天早上11點左右,我在工作休息之餘,擼了一下貓。突然,工作群響了,老大在裡面說:APP出錯了! 媽啊,這太嚇人了,因為只是說了出錯,但是沒說錯誤的資訊。所以我趕緊到APP上看看。 這果然是出錯了,而且還是簡單而粗暴的500,太嚇人了。 二、本地趕緊除錯起來! 既然線上出錯了,我們又不

Maximum sum變式

【題目描述】 對於給定的整數序列A={a1,a2,…,an}A={a1,a2,…,an},找出兩個不重合連續子段,使得兩子段中所有數字的和最大。我們如下定義函式 d(A): 我們的目標就是求出d(A)。 【輸入】 第一行是一個整數T(≤30),代表一

演算法 |

         #include <stdio.h> int a[100001],dp[100001]; int main() { int T,n; while(~scanf("%d",&n)) {

演算法優化:,雙指標遍歷(n^2),分治法(nlogn),動態規劃(n)

最大欄位和,有點類似與最長公共子序列,這裡是求連續一段求和最大的一段,比如[-2,11,-4,-4,13,-5,-2]最大求和的連續一段為11,-4,-4,13,和為16. 最基本的雙針模型遍歷,兩個指標,分別代表最大和序列的起始和終止,演算法時間複雜度O(n^2) # 以下演算法時

求陣列簡潔有效的演算法

直接上程式碼:public static int max(int[] a){ int max = 0;int zmax = 0; for (int i = 0;i<a.length;i++){ zmax += a[

基礎演算法--B

Description Given a sequencea[1],a[2],a[3]......a[n], your job is to calculate the max sum of asub-sequence. For example, given (6,-1,5,4

蠻力分治動態規劃求解問題(aardio)

最近的演算法課上要求做的一個實驗是分別用蠻力、分治、動態規劃求解最大欄位和問題。 以下是相關程式碼: 陣列求和程式段: var getsum = function(tab,frist,l

演算法設計分析課作業week3leetode--105. Construct Binary Tree from Preorder and Inorder Traversal

題目 Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may assume that duplicates do not exist in the t

演算法設計分析課作業week6leetcode--8. String to Integer (atoi)

題目 Implement atoi which converts a string to an integer. The function first discards as many whitespace characters as necessary until th

演算法設計分析課作業week7leetcode--151. Reverse Words in a String

題目 Given an input string, reverse the string word by word. Example:   Input: "the sky is blue", Output: "blue is sky the". Note: A wo