C語言程式設計100例之(13):最大子段和

来源:https://www.cnblogs.com/cs-whut/archive/2019/11/21/11902351.html
-Advertisement-
Play Games

例13 最大子段和 題目描述 給出一段序列,選出其中連續且非空的一段使得這段和最大。例如在序列2,-4,3,-1,2,-4,3中,最大的子段和為4,該子段為3,-1,2。 輸入格式 第一行是一個正整數N,表示了序列的長度。 第二行包含N個絕對值不大於10000的整數Ai ,描述了這段序列。 輸出格式 ...


例13        最大子段和

題目描述

給出一段序列,選出其中連續且非空的一段使得這段和最大。例如在序列2,-4,3,-1,2,-4,3中,最大的子段和為4,該子段為3,-1,2。

輸入格式

第一行是一個正整數N,表示了序列的長度。

第二行包含N個絕對值不大於10000的整數Ai ,描述了這段序列。

輸出格式

一個整數,為最大的子段和是多少。子段的最小長度為1。

輸入樣例

7

2 -4 3 -1 2 -4 3

輸出樣例

4

        (1)編程思路。

        可以從長度為n的數列的最左端(設為數組元素a[1])開始掃描,一直到最右端(設為數組元素a[n-1])為止,記下所遇到的最大總和的子序列。

        程式中定義變數maxsum保存最大連續子段和,cursum保存當前連續子段和。

        初始時,cursum=a[0]、maxsum=a[0]。用迴圈for (i=1;i<n;i++)對序列中的每一個元素a[i]進行掃描處理。

        在這一掃描過程中,從左到右記錄當前子序列的和(即cursum= cursum+a[i]),若這個和不斷增加(即當前a[i]為正,從而使cursum+a[i]>maxsum成為可能),那麼最大子序列的和maxsum也增加,從而更新maxsum。如果往右掃描中遇到負數,那麼當前子序列的和cursum會減小,此時cursum將會小於maxsum,maxsum也就不更新;如果掃描到a[i]時,cursum降到0時,說明前面已經掃描的那一段就可以拋棄了,這時需要將cursum置為0。這樣,cursum將從i之後的子段進行分析,若有比當前maxsum大的子段,需要更新maxsum。這樣一趟掃描結束後,就可以得到正確結果。

        (2)源程式。

#include <stdio.h>

int main()

{

   int a[200001];

   int n,i,maxsum,cursum;

   scanf("%d",&n);

   for (i=0;i<n;i++)

       scanf("%d",&a[i]);

   cursum=a[0];

   maxsum=a[0];

   for (i=1;i<n;i++)

   {

       if (cursum+a[i]>maxsum)

       {

             maxsum=cursum+a[i];

       }

       if (cursum+a[i]<0)

       {

            cursum=0;

       }

       else

          cursum= cursum+a[i] ;

   }

   printf("%d\n",maxsum);

   return 0;

}

習題13

13-1  最大差值

        本題選自洛谷題庫 (https://www.luogu.org/problem/P5146)

題目描述

HKE最近熱衷於研究序列,有一次他發現了一個有趣的問題:

對於一個序列A1 ,A2 ⋯An ,找出兩個數i,j,1≤i<j≤n,使得Aj −Ai 最大。

現在給出這個序列,請找出Aj −Ai 的最大值。

輸入格式

第一行為一個正整數n。

接下來n個整數,第k+1個整數為Ak 。

輸出格式

一行為 (Aj −Ai )的最大值

輸入樣例

10

1 3 4 6 7 9 10 1 2 9

輸出樣例

9

        (1)編程思路。

        由於求Aj −Ai 的最大值的要求是下標j>i,也就是說最大的數是在最小的數後面才符合要求,因此不能簡單地求序列的一個最大數max和一個最小數min(無法保證max一定在min的後面),然後輸出max-min作為答案。

        定義變數minnum保存序列的最小數,maxdiff保存最大差值,由於輸入n>=2,因此可以先輸入序列前兩個數a和b,賦minnum的初值為a與b中的較小數,maxdiff的初值為b-a。

        然後用迴圈for (i=3;i<=n;i++)對序列中的每一個元素Ai進行掃描處理。處理時,若當前Ai與最小數minnum的差值大於maxdiff,則更新maxdiff,這個更新一定是有效的,因為保存的最小數minnum一定在當前數Ai之前;若當前數Ai比最小數小,則更新最小數minnum為當前數Ai。

        這樣一趟掃描結束後,就可以得到正確結果。

       (2)源程式。

#include <stdio.h>

int main()

{

    int minnum,maxdiff;

    int i,n,a,b;

    scanf("%d",&n);

    scanf("%d%d",&a,&b);

    minnum=a<b?a:b;

    maxdiff=b-a;

    for (i=3;i<=n;i++)

    {

        scanf("%d",&a);

        if (a<minnum) minnum=a;

        if (a-minnum>maxdiff) maxdiff=a-minnum;

    }

    printf("%d\n",maxdiff);

    return 0;

}

13-2  連續自然數和

題目描述

對一個給定的自然數M,求出所有的連續的自然數段,這些連續的自然數段中的全部數之和為M。

例子:1998+1999+2000+2001+2002 = 10000,所以從1998到2002的一個自然數段為M=10000的一個解。

輸入格式

包含一個整數的單獨一行給出M的值(10≤M≤2,000,000)。

輸出格式

每行兩個自然數,給出一個滿足條件的連續自然數段中的第一個數和最後一個數,兩數之間用一個空格隔開,所有輸出行的第一個按從小到大的升序排列,對於給定的輸入數據,保證至少有一個解。

輸入樣例

10000

輸出樣例

18 142

297 328

388 412

1998 2002

        (1)編程思路。

        定義兩個變數left和right用於指示待求子序列的最左端和最右端,初始時令left=1,right=(int)sqrt(2.0*n),顯然此時1+2+…+right的和值sum(sum=(right-left+1)*(left+right)/2)會非常接近n。之後進行如下操作過程:

        1)比較sum與n,根據sum與n的大小關係進行不同處理。簡單描述就是若sum值大了,去掉子序列最左端的數,從而減少sum值;若sum值小了,將最右端數的下一個數加入子序列,從而增大sum值;若sum與n相等,則找到一個子序列的和等於n,輸出此時子序列的left和right值,輸出後和值sum中去掉子序列最左端的數以便繼續向後找到其他的子序列。

        2)重覆上面的過程,直到left==right,此時子序列中只有一個數,搜索結束,退出。

      (2)源程式。

#include <stdio.h>

#include <math.h>

int main()

{

     int left,right,sum,n;

     scanf("%d",&n);

     left=1;   right=(int)sqrt(2.0*n);

     sum=(right-left+1)*(left+right)/2;

     while (left<right)

     {

           if (sum==n)

           {

                    printf("%d %d\n",left,right);

                    sum-=left++;

           }

          else if (sum<n)

           {

                      right++;

                      sum+=right;

           }

           else

           {

                     sum-=left;

                     left++;

           }

     }

    return 0;

}

13-3  Subsequence

本題選自北大POJ 題庫(http://poj.org/problem?id=3061)。

Description

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.

Input

The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.

Output

For each the case the program has to print the result on separate line of the output file.if no answer, print 0.

Sample Input

2

10 15

5 1 3 5 10 7 4 9 2 8

5 11

1 2 3 4 5

Sample Output

2

3

        (1)編程思路。

         本題題意是:輸入整數N和S,N表示數列中元素的個數,S表示一個和值,然後輸入數列中的N個元素,求一個子序列長度最短的連續子序列,使子序列中全部元素的和大於等於S。輸出這個子序列的長度。

        用兩個變數i和j表示子序列的兩個端點,初始時i和j的值均為0,和值sum=0。

        這個搜索過程簡單描述為:先讓右端點移動,並將右端點的值累加到和值sum中(語句為sum+=a[j++]),直到sum大於等於S,按要求更新答案;然後再讓左端點移動,並將左端點的值從和值sum中減掉(語句為sum-=a[i++];),也隨之更新答案,直到出現sum小於S後,右端點再移動。重覆這個過程,直到右端點越過了原序列的最後一個數據。 

       (2)源程式。

#include <stdio.h>

int main()

{

     int t,i,j,a[100001],n,s,sum,minx;

     scanf("%d",&t);

     while(t--)

     {

        scanf("%d%d",&n,&s);

        for(i=0;i<n;i++)

           scanf("%d",&a[i]);

        i=0;

        minx=0x7fffffff;

        sum=0;

        for (j=0;j<n;)

        {

             while(sum<s && j<n)

                 sum+=a[j++];

             while(sum>=s)

            {

                 if (minx>j-i) minx=j-i;

                 sum-=a[i++];

            }

        }

        if (minx==0x7fffffff)

             minx=0;

        printf("%d\n",minx);

    }

    return 0;

}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 為了加強項目的介面安全程度,需求如下 1 var options = { 2 // 前端需要傳送的數據加密 3 data: { 4 abc: 123, 5 bcd: 123, 6 cds: '撒旦教付貨款12313', 7 }, 8 // 模擬後端返回base64碼 9 key: 'NWxCZUZ3 ...
  • 獲取兩個數字中的最大值 用if-else語句 var num1 = 10; var num2 = 100; if (num1 > num2) { console.log(num1); } else { console.log(num2); } 兩個分支,最終的結果是兩個分支中的一個,像這種情況可以使 ...
  • 一、頁面佈局 ​ 預設九宮格圖 九宮格占點陣圖 HTML頁面代碼: 二、頁面樣式 九宮格佈局相關CSS頁面樣式: 三、代碼邏輯 Luck幸運抽獎函數方法: 獎品列表DOM拼接: javascript / 獎品列表排序 / let sortList = function(data, el) { var ...
  • 開始學些Html的時候主要進行一些簡單的靜態網頁的處理: 1、HTML 標題 HTML 標題(Heading)是通過 h1-h6 加中括弧<>等標簽進行定義的。 2、HTML 段落 HTML 段落是通過 標簽進行定義的。 3、HTML 鏈接 HTML 鏈接是通過《a》標簽進行定義的。 4、HTML ...
  • 上篇介紹了一個簡單的UDP服務框架,但是面對海量的請求,同步框架顯然有點力不從心。於是在我接手好友系統的介面服務的時候,就採用了一個強大的非同步框架——MCP框架。 MCP框架是一個多進程非同步框架,支持UDP、TCP和http,結構很靈活,可以根據需要將各組件像搭積木一樣組裝。下麵是MCP最基礎的進程 ...
  • 畢業後加入了一家大型的互聯網公司的音視頻產品部門做後臺開發,其實我本身是學習自動化的,研究生的方向嵌入式系統,對互聯網可是一知半解,因此能進入這樣一個大公司還是很幸運的。 剛開始工作的半年應該是在上份工作最快樂的時光,那時候我們十來個人被抽調出來做好友系統,由Z組長負責。從產品到開發,大部分都是新入 ...
  • 簡介:應用程式開髮長期以來一直是IT部門和業務部門面臨的問題。 IT部門總是被新的應用程式需求弄得不堪重負。他們不可能完成業務部門想要完成的每一個項目。 同時,業務部門的用戶厭倦了等待,並開始完全繞過IT部門。 今天,我們來探索一下“低代碼開發”這個概念,並闡述它將如何幫助解決這個問題,為企業應用開 ...
  • CAD繪圖一直是一個謎一樣的存在,說它簡單吧,很多人都無法完全精通,說它難吧,很多人也都自學成才了。 如何學好CAD繪圖是個難題,但是老話說的好,只要思想不滑坡,辦法總比困難多,掌握以下這些CAD繪圖技巧,你就相當於裝了一個電動馬達,繪圖不止比別人快一步。 一、設置圖層 在一開始繪圖的時候很多小伙伴 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...