1. 程式人生 > >輸入n個數,最壞情況下用 n + logn

輸入n個數,最壞情況下用 n + logn

這個題我一開始是遞迴 從底層出發 比到頂層 顯然時間複雜度不允許

後來想了一種n時間複雜度的

開兩個數用來維護最大值和最小值就可以了,什麼意思呢

比如 1 3 6 2 8 4 0 0 8是我們要求的陣列

int last = Integer.Min_Value;

int cur = Integer.Min_Value;

分別代表了上一個最大值和當前最大值

我們走到a[0] cur = 1

到a[1] cur=3 last = 1

繼續走 cur=6 last=3

...

維護到最後,這兩個數就是最大值和次大值了

但是既然要求的是n+logN,那就用競賽的思想(網上看的)

分析:

例如這n(n=8)個數分別是:8 7 9 2 3 6 10 12

第一輪比賽:(8,7) (9,2) (3,6) (10,12) 比較了4次

得到第一輪的入選者:8 9 6 12

第二輪比賽:(8 9) (6 12) 比較了2次

得到第二輪的入選者:9 12

第三輪比賽:(9 12) 比較了1次

得到第三輪的入選者:12 12既是比賽的冠軍

以上得到冠軍總共比較了7次,即n-1次

只有和冠軍比過的人才有可能是亞軍,這句話就是關鍵。

為什麼只有和冠軍比過的人才有可能是亞軍,因為都沒和冠軍必過,證明肯定分組不是和冠軍一個分組的而且別另外的數給虐了。所以我們只需要開一個int變數去維護亞軍就可以了。

顯然第一輪變數 維護的亞軍=10

第二輪是6 所以維護的亞軍還是=10

比到最後 維護的還是10

所以就得出來了(如果有更大的就會更新這個量)

一共7+3=10次

但是在比賽之前你咋知道誰是冠軍?難道你和演員的誕生一樣有黑幕?

所以正確的做法是空間換時間,把每組比賽都存放進不同的陣列中。

之後我們進行比賽得出了12是冠軍,我們就可以通過12在陣列中的定位,找到和他比的人。

比如說

8 7 9 2 3 6 10 12

8 9 6 12

9 12

12

我們可以把10,6,9入我們的新陣列繼續去比(但是注意不能像上面一樣比了),因為資料大的時候,每次和冠軍比的人有很多所以新陣列繼續去按之前的方式一樣比。

就搞定啦!

最後思考一下最壞情況 並引出另一種方法

就是比如9個數 第一次複雜度為n 你找到了最大值

在找的過程中我們把9個數分成了3組 分別求出了最大值 這個時候我們想求次大值 難道就是這3組值中的第2大的值嗎?錯了!這個時候就出現了最壞情況,次大值可能是3組值中第二大的值,但是也完全有可能出現在最大值的那一組中!所以這就是最壞情況的麻煩之處。所以我們在第一次找的過程中,不僅要把9個數分成三組求出最大值,還要求出次大值,那麼這樣就規避了最壞情況。我們第一輪找求出了最大值,我們定位那一組,找到那一組的次大值。再定位次大值的那一組,找到那一組的最大值,再進行比較,就搞定啦!

程式碼就不貼啦!

相關推薦

輸入n個數情況 n + logn

這個題我一開始是遞迴 從底層出發 比到頂層 顯然時間複雜度不允許後來想了一種n時間複雜度的開兩個數用來維護最大值和最小值就可以了,什麼意思呢比如 1 3 6 2 8 4 0 0 8是我們要求的陣列int last = Integer.Min_Value;int cur = I

給定陣列a[0:n-1]試設計一個演算法情況[3n/2 -2 ] 次比較找出a[0:n-1]中元素的大值和小值;教材2-15

給定陣列a[0:n-1]試設計一個演算法,在最壞情況下用[3n/2 -2 ] 次比較找出a[0:n-1]中元素的最大值和最小值; 解:要求對於陣列用小於【3n/2-2】的比較次數找到兩個最值 可以用陣列第一個元素來初始化max,min 然後遍歷陣列,分別和max,min比較,一遍就可以找

合併兩個長度分別為m和n的有序表情況需要比較m+n-1次

最壞的情況就是交叉的情況: 比如 1 3 52 4 6 設上鍊指針p,下鏈q,每次比較後較小節點依次作為“合併後連結串列的節點”,同時較小鏈指標後移。某鏈指空後不再比較。則樓上所給的第一個例

[百度面試題]100層樓球可能會在某一層樓摔2個球情況幾次測試可以找出該樓層

該題還可以擴充套件,比如說給更多的球,如3個球,多少次測試可以找出樓層。 分析如下: 用動態規劃解這個問題 設f(a, b)為a個球做b次測試可以測試到的樓層數,可以確定的樓層數即為f(a, b) + 1,因為第1層不需測試,需要測試的樓層號僅僅為[2, f(a, b) +

100層樓有一個雞蛋如果確定剛好摔碎的那個樓層情況最少需要摔多少次?

分析:這道題我們應反過來考慮,就是用a塊石頭扔b次至多一定可分辨層數X(a,b)。先從最簡裝的一塊石頭考慮,很顯然,X(1,1) = 1X(1,2) = 2X(1,3) = 3.X(1,i) = i再考慮二塊石頭,顯而易見X(2,1) = 1對於X(2,2),我們可這樣考慮,當我們扔第一次後,有兩種可能:破和

夜深人靜寫演算法———線性時間選擇(分治情況處理)

一:     線性時間選擇中,最壞情況下時間複雜度為O(n^2) , 但如果線上性時間內找到一個劃分基準,使得按照這個基準所劃分的兩個子陣列的長度至少為原陣列的k倍( 0<k<1)。 二: (1) 將n個輸入的元素分成 (n-4)/5組,每一組都是5個元素,可

演算法設計:有n個數範圍是從1到n且只有唯一的兩個數相同如何快的求相同的這個數值?

為了方便問題描述,假設n = 10,即陣列a[10]裡有10個數,範圍是從1到10,且裡面只有兩個數的值是相同的。如何求這個相同的數值。 常規思路: 1,先氣泡排序,然後用while迴圈找出這個相同的數值 2,直接用冒泡的思路,i從0到n-2,j = i+1,依次比,找出相

排序演算法--時間複雜度(平均時間情況)、空間複雜度

1、時間複雜度:一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式f(n),演算法的時間量度記作:                                            

shell指令碼之任意輸入n個數判斷大值小值總和

#!/bin/bash ##任意輸入n個數,判斷最大值,最小值,總和 sum=0 n=0 read -p "please input the count of number:" count #max

輸入個數輸出其大公約數和小公倍數並輸出所有的公約數

輸入兩個數,求其最大公約數和最小公倍數,並輸出所有的公約數 以下分別用三種方法求最大公約數,詳細程式碼如下: #include <iostream> using namespace std; //求最大公約數:求差法 void div1(int m,int n){ i

寫一個函式輸入個數隨機生成N條郵箱

寫一個函式,這個函式的功能是,傳入一個數字,產生N條郵箱,產生的手機號不能重複。郵箱前面的長度是6 - 12之間,產生的郵箱必須包含大寫字母、小寫字母、數字和特殊字元 import random

輸入個數輸出其大值

#include<stdio.h> int main() { int t,a,b,c; scanf("%d%d%d",&a,&b,&c); if(a>b) if(a>c) t=a; else t=c; el

C語言 習題 輸入n個數輸出不重複的數及它們的和

難住本小白的一道c語言題目,搞了兩天才出來,不多比比,直接上題 題目:輸入n個整數,輸出不重複整數及它們的和。 //講真,當時那道題,讀了兩遍愣是沒懂······ 此題筆者認為有兩個難點, 1.“如何輸入n個整數”,當按下回車鍵時結束輸入,其中n是不定的,(不能要求先輸入n的值,那樣難度直接

(03)從鍵盤輸入個數求出這個數的階乘n!。

題目描述  從鍵盤輸入一個數,求出這個數的階乘,即 n!。 演算法思想 首先要清楚階乘定義,所謂 n 的階乘,就是從 1 開始乘以比前一個數大 1 的數,一直乘到 n,用公式表示就是:1×2×3×4×…×(n-2)×(n-1)×n=n! 具體

輸入n個數判斷正數.負數.0的個數

#include<stdio.h> int main() { float p[100]; int i, m, n, k, l; m = 0; k = 0; l = 0; scan

C++ 輸入5個數大值和第一 個數交換小值和最後一個數交換

#include "iostream" using namespace std; int main() { const int n=6; //靈活定義陣列的大小 int

從鍵盤上輸入個數編寫一個max函式可以輸出三個數大的數字

int max(int a,int b,int c ); int main(int argc, const char * argv[]) {     int a,b,c;     scanf("%d",&a);     scanf("%d",&b);    

給出n個數找出這n個數大值小值以及這些數字的和

<div class="sec_header">問題描述</div><div class="sec_cont"><p>給出n個數,找出這n個數的最大值,最小值,和。</p></div><div c

劍指offer之找出陣列中小的n個數之優先佇列

這道題最簡單的就是排序,時間複雜度O(nlogn)。不再講述。這裡可以使用優先佇列,時間複雜度O(nlogk)。注意檢驗k的合法性,不然初始化佇列時會報錯。import java.util.ArrayL