1. 程式人生 > >數字之魅:尋找陣列中的最大值和最小值

數字之魅:尋找陣列中的最大值和最小值

陣列是最簡單的一種資料結構。我們經常碰到的一個基本問題,就是尋找整個陣列中最大的數,或者最小的數。這時,我們都會掃描一遍陣列,把最大(最小)的數找出來。如果我們需要同時找出最大和最小的數呢?
對於一個由N個整陣列成的陣列,需要比較多少次才能把最大和最小的數找出來呢?
這個題目比價簡單,主要方案如下:
方案一:分別求最大和最小值。這是一種比較常規的解法。可以分別求出陣列的最大值和最小值,這樣,我們可以採用最基本的冒泡思想遍歷兩次(2N)就能求解
方案二:分組求解。由於前面的需要遍歷2N次。這裡為了使其遍歷的次數減少,我們可以採用分組。
  (1) 按順序將陣列中相鄰的兩個數分在同一組,邏輯上分組,實際什麼都不用做;
  (2) 比較同一組的兩個數,將大的數放在偶數位上,小的放在奇數位上;
  (3) 最後,從偶數位上求最大值,奇數位上求最小值即可。
  這樣一共需要比較1.5N次。
這種辦法雖然比較次數變少了,但卻破壞了原陣列,因為我們交換了陣列資料的位置。
方案三改進的分組。此種方法可以避免破壞原資料的順序。
  (1) 用兩個變數max和min分別儲存當前的最大值和最小值。
  (2) 同一組的兩個數比較完之後,不再調整順序,將其中較大的與當前max比較,較小的與min比較;
  (3) 如此反覆,直到遍歷完整個陣列。
  整個過程比較次數也為1.5N次但是沒有對原資料進行更改,如果資料是在只讀儲存區,那麼該方法就能派上用場了。
方案四:分治策略。該方法用到歸併排序中的merge()函式,雖然方法不一樣,但是可惜的比較的次數還是沒有減少,仍然為1.5N次。在求解的過程中分別求出前後N/2個數的min和max,然後,取較小的min,較大的max即可。
這裡主要是提醒一下經常用的兩種思路:快排你的partion()和歸併裡的merge(),這兩個函式的解決問題的思路十分常用。通常在解決問題的時候,要想到他們,是一種解決的思路。

擴充套件問題
如果需要找出N個數中的第二大數,需要比較多少次呢?是否可以使用類似的分治思想來降低比較的次數呢?

思路一:
 用兩個變數分別存最大值max1和次大值max2,遍歷陣列:
    初始化:max1=arr[0],max2=0;
    先與max2比較,如果比max2大再和max1比較;
  如果arr[i] >max1,則更新max=arr[i],max2=max1;
  否則如果arr[i] > max2 && arr[i]< max1,則更新max2=arr[i];
  否則,不進行更新操作。
  這個方法最多的比較次數為2*N次,最大的值在最後面;最小N次第一個和第二個恰好就是最大和第二大的數。
思路二:快速選擇演算法的思想。

 先尋找出第k大的整數,然後再通過兩次遍歷前k大的數字找出第二大的數字,因為找出的前k個元素是不保證排序的。比較的次數為:找出前K個元素次時:最好k次,最壞N次。然後在前k個元素中找出第K個元素:比較的次數:k+k-1次。所以比較的次數為:最好3k-1次,最壞:N+2k-1次。