1. 程式人生 > >演算法探究:線性時間選擇問題

演算法探究:線性時間選擇問題

一.什麼是線性時間選擇問題

前幾天,女票問到了快速排序,然後我看了一下程式碼,發現不對呀,為什麼連基本的遞迴都沒有,後來仔細看了整個程式之後,發現,這個程式並不是普通的快速排序,而這也就引出了今天要講的問題,線性時間選擇問題,其實它也就是隨機化的快速排序,以求加快效率,最快求解。

二.大體思路

RandomizedSelect演算法,因為該演算法是想要求解在一個序列中某一個等級大小的數,那麼這個演算法的大體思路其實就是隨機選取基準元素,根據基準元素進行分割槽,小的分在左邊,大的分在右邊,每次分完之後返回基準元素所在陣列中的索引,同時比較等級,小的話在左邊查詢,大的話在右邊查詢,那麼這樣說的話大家是不是又想到了快速排序演算法,是不是特別熟悉呢。

三.具體實現

談及具體實現的話,我還是先把程式碼貼上來然後一點一點地分析。

int RandomizedSelect(int a[],int low,int high,int k)
{
  if(low==high)
    return a[low];
  int i=RandomizedPartition(a,low,high);
  int j=i-low+1;
  if(k<=j)
    return RandomizedSelect(a,low,i,k);
  else
    return RandomizedSelect(a,i+1,high,k-j);
}
這就是其中最核心的部分。

03,04:和快排類似,倘若low==high,那麼說明基準點已經到了我們需要的等級的位置,直接返回當前值。

05:假如不相等,那麼就得重新分割槽。

06--10:重新分割槽之後,就得根據基準元素返回的索引考慮接下來往哪邊尋找。

接下來是隨機選取基準元素的函式

int RandomizedPartition(int a[],int low,int high)
{
  Random rm = new Random();
  int i = rm.Next(low,high);
  Swap(a[i],a[low]);
  return Partition(a,low,high);
}
前兩句就是在新的分割槽裡面尋找新的隨機基準點,在這裡我們把隨機選取的基準點和第一個元素交換,因為後面分割槽的時候一直以第一個元素為基準,後兩句就是重新分割槽。

最後就是分割槽函式,其實這裡就用到了快排

int Partition(int a[],int low,int high)
{
  int i=low,j=high+1;
  int x=a[low];
  while(true)
  {
        while(a[++i]<x&&i<high);
        while(a[--j]>x);
        if(i>=j) break;
        Swap(a[i],a[j]);
  }
  a[low]=a[j];
  a[j]=x;
  return j;
}

相信這裡就不用過多解釋了,很容易理解。

最後附上整個例項。

#include<iostream>  
#include<cstdlib>
#include<time.h>
using namespace std; 
 
void Swap(int &a,int &b) 
{ 
  int tmp=a; 
  a=b; 
  b=tmp; 
} 
 
int Partition(int a[],int low,int high) 
{  
  int i=low,j=high+1; 
  int x=a[low];
  while(true)
  {
	while(a[++i]<x&&i<high);
	while(a[--j]>x);
	if(i>=j) break;
	Swap(a[i],a[j]); 
  } 
  a[low]=a[j];
  a[j]=x; 
  return j; 
} 
 
int RandomizedPartition(int a[],int low,int high) 
{  
  Random rm = new Random();
  int i = rm.Next(low,high);
  Swap(a[i],a[low]); 
  return Partition(a,low,high); 
} 
 
int RandomizedSelect(int a[],int low,int high,int k) 
{ 
  if(low==high) 
    return a[low]; 
  int i=RandomizedPartition(a,low,high); 
  int j=i-low+1; 
  if(k<=j) 
    return RandomizedSelect(a,low,i,k); 
  else 
    return RandomizedSelect(a,i+1,high,k-j); 
} 
 
/* 測試 */ 
int main() 
{ 
  int a[]={4,7,9,5,8,3,0,1}; 
  int k=2; 
  int result=RandomizedSelect(a,0,7,k); 
  cout<<"第"<<k<<"小的元素是"<<result<<endl; 
  return 0; 
} 



四.總結

首先要強調的是,RandomizeSelect演算法,最好能夠達到O(n)的時間複雜度,這時很不錯的,另外最壞也是O(n*n),而不是像一些普通演算法,平均複雜度是O(n*n),其次呢,該演算法跟資料的準備還是有比較大的關係的,這個我們之後再另外寫一篇好好敘述。總的說來呢,我主要是看到之後耳目一新,自己實現了一下,其實我完全是演算法方面的小白,如果有錯誤還希望指正。

  email: [email protected]  

  謝謝!

相關推薦

演算法探究線性時間選擇問題

一.什麼是線性時間選擇問題 前幾天,女票問到了快速排序,然後我看了一下程式碼,發現不對呀,為什麼連基本的遞迴都沒有,後來仔細看了整個程式之後,發現,這個程式並不是普通的快速排序,而這也就引出了今天要講

夜深人靜寫演算法——線性時間選擇(分治,陣列第n小的數)

線性時間選擇:求陣列中第n小的值 一:    解決的方法是基於快速排序解決的,當快速排序進行一次排序的時候,在參考點左側的都是比參考值小的,右側都是比參考點大的。   (1)參考點的下標等於 n-1,說明參考點就是第n小的值。   (2)參考點的下標大於n-1 , 說

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

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

BFPRT演算法 線性時間選擇第k小元素

文章目錄 BFPRT演算法 1. 應用場景 2. 基本思想 3. 演算法實現 4. 複雜度分析 5. References BFPRT演算法 1. 應用場景 線性時間內,從無序列表找到

【分治法】線性時間選擇(轉)

算法思路 ont 位置 劃分 得到 子數組 als lena part 轉自:http://blog.csdn.net/liufeng_king/article/details/8480430 線性時間選擇問題:給定線性序集中n個元素和一個整數k,1≤k≤n,要求找出這n

資料結構與演算法分析線性結構(3)

堆疊 1.計算機如何進行表示式求值     算術表示式: 由兩類物件構成:運算數,運算子號 不同運算子號優先順序不同    ①中綴表示式:把運算子號放在兩個運算數之間:a+b*c-d/e     &

線性時間選擇

問題:給定線性序集中n個元素和一個整數k,1<=k<=n,要求找出這n個元素中第k小的元素。 我們採用快速排序的思想來解決這個問題。首先我們要找到基準的位置,如果基準的位置小於k,則表示第k小的元素在基準的後面,否則在基準的前面。 如果能線上性時間內

分治法-線性時間選擇

線性時間選擇問題: 給定線性序集中n個元素和一個整數k,1≤k≤n,要求找出這n個元素中第k小的元素。 1、隨機劃分線性選擇 基本思想: 只對劃分出的子陣列之一進行遞迴處理。 子陣列的選擇與劃分元和k相關。 #include <iostream> #i

第三方開源庫日期時間選擇器(TimePickerDialog)+ 省市區三級聯動(CityPicker) + 一級滾動

TimePickerDialog Android時間選擇器,支援年月日時分,年月日,年月,月日時分,時分格式,可以設定最小時間和最大時間(精確到分)。 效果圖 gradle compile 'com.jzxiang.pickervie

線性時間選擇問題

1、問題描述 給定的線性集中n個元素和一個正整數k(1≤k≤n),要求線上性時間內(即時間複雜度為O(n))找出這n個元素中第k小的元素。 2、演算法設計思想 將n個元素劃分成n/5組,每組5個元素,只可能有一組不是5個元素。再用氣泡排序法,將每組內的五個

演算法導論》——最壞時間線性時間選擇演算法

《演算法導論》——最壞時間為線性時間的選擇演算法 該演算法與期望時間為線性時間的選擇演算法的最大區別就是該演算法的partition中不是隨機的以某一個數作為基準,而是將中位數的中位數傳入作為基準,返回中位數的中位數在序列中的位置。 步驟如下 1: 將輸入陣列的n個元素劃分為 n/5

演算法導論》——期望為線性時間選擇演算法

《演算法導論》——期望為線性時間的選擇演算法 #include "iostream" #include "algorithm" using namespace std; // 一般的快速排序,在最壞的情況下時間複雜度為n2, 這在輸入資料有序的情況下會出現,我們應該儘量去避免它

期望為線性時間選擇演算法

《演算法導論》第9章Randomized_Select演算法 Randomized_Select的原理與思想 從一個數組當中尋找第i小的元素,最簡單最暴力的方法就是將整個陣列按照升序進行排序操作,那麼第i個元素就是第i小的元素。 如果是以這種方式,那麼時間複

KMP演算法O(n)線性時間字串匹配演算法

KMP演算法包括兩個子程式。其中KMP-MATCHER指字串匹配子程式,COMPUTE-PREFIX則為部分匹配表NEXT[]生成程式。《演算法導論》一書中有一句話,我認為說的非常透徹:“這兩個程式有很多相似之處,因為它們都是一個字串對模式P的匹配:KMP-MATCHER是文字T針對模式P的

線性時間排序 三種非基於比較的內部排序演算法

未完待續。。。。。。 一、基於比較的排序演算法,在最壞情況下,最少都需要用O(nlgn)次比較。 下面來證明一下。 不妨我們假設 排序都是從小到大進行排序。 說明: 用1、2、3來表示三個元素,用π(1)、π(2)、π(3)來表示該元素對應的值。用尖括號〈1,3,2〉表示π

最壞情況為線性時間選擇算法

n個元素 pan 時間復雜度 向下取整 賦值 選擇 spa 向上取整 pri 算法select可以確認一個有n>1個不同元素的輸入數組中第i小的元素。(如果n=1,則select只返回它的唯一輸入數值作為第i小的元素。) 1.將輸入數組的n個元素劃分為n/5(向下取

Android零基礎入門第57節日期選擇器DatePicker和時間選擇器TimePicker

oncreate ted show imageview bce min date 教程 運行程序 在實際開發中,經常會遇見一些時間選擇器、日期選擇器、數字選擇器等需求,那麽從本期開始來學習Android中常用選擇器,今天學習的是DatePicker和TimePicke

bootstrap-datetimepicker基於twitter bootstrap的日期/時間選擇控件

add 時間選擇控件 選擇 html pre Language link sset input bootstrap-datetimepicker是一個基於twitter bootstrap的簡單日期/時間選擇控件。 <!DOCTYPE HTML> <h

筆記Tarjan算法 求解有向圖強連通分量的線性時間的算法

true fff lan number lock 無環 還需 sin 第一次 Tarjan他爾賤算法 求解有向圖強連通分量的線性時間的算法 百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825

已知長度為n的線性表A採用順序儲存結構,請寫一個時間複雜度為O(n)、空間複雜度為O(1)的演算法,該演算法可刪除線性表中所有值為item的資料元素。

語言:C++ #include <iostream> using namespace std; typedef int ElemType; //定義 #define MAXSIZE 100 typedef struct {ElemType *elem; int length;}Sq