1. 程式人生 > 電腦技巧 >Win10系統將“執行”固定到開始選單的方法

Win10系統將“執行”固定到開始選單的方法

題目:最大子列和問題

問題描述:

給定K個整陣列成的序列{N1​​,N2​​, ...,NK​​ },“連續子列”被定義為{Ni​​,Ni+1​​, ...,Nj​​ },其中1ijK。“最大子列和”則被定義為所有連續子列元素的和中最大者。例如給定序列{ -2, 11, -4, 13, -5, -2 },其連續子列{ 11, -4, 13 }有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。

本題旨在測試各種不同的演算法在各種資料情況下的表現。各組測試資料特點如下:

  • 資料1:與樣例等價,測試基本正確性;
  • 資料2:102個隨機整數;
  • 資料3:103個隨機整數;
  • 資料4:104
    個隨機整數;
  • 資料5:105個隨機整數;

輸入格式:

輸入第1行給出正整數K (100000);第2行給出K個整數,其間以空格分隔。

輸出格式:

在一行中輸出最大子列和。如果序列中所有整數皆為負數,則輸出0。

輸入樣例:

6
-2 11 -4 13 -5 -2

輸出樣例:

20

演算法描述:

#include<iostream>
using namespace std;
int MaxSubSum(int* a, int left,int right )
{
    int sum=0;
    if(left==right)
    {
        sum=a[left]>0?a[left]:0
; } else { int mid=(left+right)/2; int leftsum=MaxSubSum(a,left,mid); int rightsum=MaxSubSum(a,mid+1,right); int sum1=0; int lefts=0; for(int i=mid;i>=left;i--) { lefts +=a[i]; if(lefts>sum1) sum1
=lefts; } int sum2=0; int rights=0; for(int i=mid+1;i<=right;i++) { rights +=a[i]; if(rights>sum2) sum2=rights; } sum=sum1+sum2; if(sum<leftsum) sum=leftsum; if(sum<rightsum) sum=rightsum; } return sum; } int main() { int n,a[100000]; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; cout<<MaxSubSum(a,0,n-1); return 0; }

Tips:

從一開始考慮,我們也許會想到暴力解法:即用兩層迴圈列舉起點和終點,這樣就嘗試了所有的子序列,然後計算每個子序列的和,然後找到其中最大的即可。但此演算法複雜度為O(N^3),效率低。

根據暴力解法我們可以進行一個小的優化:如果我們有這樣一個數組sum,sum[i]表示第1個到第i個數的和。那麼我們就可以用sum[j] - sum[i-1]快速計算第i個到第j個這個序列的和。這樣的話,我們省掉最內層的迴圈,演算法複雜度便到了O(N^2),大大提高了效率。

但是老師提出了一個可以更加優化的想法:利用分治法進行劃分。分為左半序列、右半序列、中間序列,簡單分析如下:

首先,我們可以把整個序列平均分成左右兩部分,答案則會在以下三種情況中:
1、所求序列完全包含在左半部分的序列中。
2、所求序列完全包含在右半部分的序列中。
3、所求序列剛好橫跨分割點,即中間序列部分。

我們只要計算出:以分割點為起點向左的最大連續序列和、以分割點為起點向右的最大連續序列和,這兩個結果的和就是第三種情況的答案。因為已知起點,所以這兩個結果都能在O(N)的時間複雜度能算出來。

遞迴不斷減小問題的規模,直到序列長度為1的時候,答案就出來了。

演算法時間及空間複雜度分析:

這個演算法的時間複雜度是O(NlogN),T(N)=2*T(N/2)+O(N)根據主定理得出最終結果是O(NlogN)。T(N/2)是將問題分成左右兩邊兩個一樣的問題,得到左右兩邊的遞迴結果,規模變成N/2。O(N)是得到跨邊界最大子列和,左右掃描,每一個數都被掃描了一次,所以時間複雜度是O(N)

空間複雜度O(1),因為用到了一個確定的陣列。

心得體會:

上機實踐通過老師提供思路和想法,自己和同伴進行程式碼的編寫。其實還是有那麼一點點困難的。但是在兩個人的努力下和老師的講解下,慢慢理解開啟思路,就感覺輕鬆了很多。分治法的思想是需要我們在編寫程式碼的過程中慢慢培養的,希望自己在學習的過程中不斷培養演算法的多種優化思想,能夠逐漸在編寫過程中開拓自己的思維思路。