計數排序,傳說中時間複雜度O(n+k)的排序演算法
基本思想
假設數序列中小於元素a的個數為n,則直接把a放到第n+1個位置上。當存在幾個相同的元素時要做適當的調整,因為不能把所有的元素放到同一個位置上。計數排序假設輸入的元素都是0到k之間的整數。
回到頂部參考程式碼
#include <stdio.h> void COUNTINGSORT(int *A, int *B, int array_size, int k) { int C[k+1], i, value, pos; for(i=0; i<=k; i++) { C[i]回到頂部= 0; } for(i=0; i< array_size; i++) { C[A[i]] ++; } for(i=1; i<=k; i++) { C[i] = C[i] + C[i-1]; } for(i=array_size-1; i>=0; i--) { value = A[i]; pos = C[value]; B[pos-1] = value; C[value]--; } } int main() { int A[8] = {2, 5, 3, 0, 2, 3, 0, 3}, B[8], i; COUNTINGSORT(A, B, 8, 5); for (i=0; i<= 7; i++) { printf("%d ", B[i]); } printf("\n"); return 0; }
圖示
對於資料2 5 3 0 2 3 0 3程式執行的過程如下圖所示:
現在有個問題,若必須是0到n的自然數,是不是用途很小?我想了想,其實可以任意整數的,即找出最小的數來,看看與0的距離d,把所有的數同時減去d,劃到0到n的範圍內,計數排序。到最後待恢復就可以了。
計數排序的複雜度為Ο(n+k)(其中k是整數的範圍),快於任何比較排序演算法。[1-2] 當然這是一種犧牲空間換取時間的做法,而且當O(k)>O(n*log(n))的時候其效率反而不如基於比較的排序(基於比較的排序的時間複雜度在理論上的下限是O(n*log(n)), 如歸併排序,堆排序)
實現
#include <iostream>
using namespace std;
const int MAXN = 100000;
const int k = 1000; // range
int a[MAXN], c[MAXN], ranked[MAXN];
int main() {
int n;
cin >> n;
for ( int i = 0; i < n; ++i) {
cin >> a[i];
++c[a[i]];
}
for ( int i = 1; i < k; ++i)
c[i] += c[i-1];
for ( int i = n-1; i >= 0; --i)
ranked[--c[a[i]]] = a[i];
for ( int i = 0; i < n; ++i)
cout << ranked[i] << endl;
return 0;
}
|
C語言實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
相關推薦計數排序,傳說中時間複雜度O(n+k)的排序演算法基本思想 假設數序列中小於元素a的個數為n,則直接把a放到第n+1個位置上。當存在幾個相同的元素時要做適當的調整,因為不能把所有的元素放到同一個位置上。計數排序假設輸入的元素都是0到k之間的整數。 回到頂部 參考程式碼 #include & 並行排序演算法——時間複雜度O(n)的排序法最近老師講了並行的排序演算法,讓我對這個原來不是很瞭解的排序演算法產生了濃厚的興趣。並行排序方法,是指採用平行計算的方法對一組資料進行排序,理論上是在類似內排序的環境下,採用多核並行的方法讓時間降低,排序的複雜度最好的情況下能降低至O(n)左右。 排序的實質 一個時間複雜度O(n),空間複雜度為O(1)的排序演算法其實就是利用Hash的思想,開闢一個固定長度的hash陣列用於標記待排序陣列的資料元素是否出現過。由於固定長度的hash陣列,所以空間複雜度與待排序陣列資料規模n沒有關係,也就是說空間複雜度為O(1)。 Morris遍歷詳解——二叉樹先序中序後序遍歷( 時間複雜度O(N),空間複雜度O(1) )Morris二叉樹遍歷: 來到當前的節點:Cur 如果Cur無左孩子,Cur向右移動 (Cur = Cur.right) 如果Cur有左孩子,找到Cur左子樹上最右的節點,記為 mostright 陣列中只出現一次的數字,時間複雜度O(n),空間複雜度O(1)的解法題目:一個整型數組裡除了兩個陣列外,其他的數字都出現了兩次,要找出這兩個數字。 異或運算有一個性質:任何數異或它自己,結果都是0;這樣如果題目變成只有一個數字只出現一次,其他數字均出現兩次,這樣我們從頭到尾異或陣列中的每一個數字,那麼最終的結果就是隻出現一次的數字 尋找主元素演算法(時間複雜度O(N),C#)主元素問題:大小為N的陣列A,其主要元素是一個出現次數超過N/2的元素。 最近在學習演算法,書上發現這樣一道題,並且提供了一種遞迴演算法的概要,但是感覺不是特別好(遞迴判斷(時間複雜度大於O(N)了),還要對N的奇偶做出判斷以及使用附加陣列B),網上看了一下有一個SEO排行最靠前的(不說名字了, 找出大陣列array中第k大的元素(要求時間複雜度O(n))具體的程式碼實現:import java.util.Stack; /** * @author wuwh * @date createTime:2016年3月6日 上午12:23:14 */ public class KthBiggest { public static 八大排序演算法JAVA實現(時間複雜度O(n-logn)篇)本文講述時間複雜度為n*logn的排序演算法:歸併排序、快速排序、堆排序以及希爾排序的原理、Java實現以及變形應用。 一、歸併排序 原理:把兩個有序數列合併為一個有序數列。需遞迴實現。 Java實現: 1 public int[] mergeSort(in 八大排序演算法JAVA實現(時間複雜度O(n-n)篇)本文主要描述3個時間複雜度為n2的排序演算法:氣泡排序、選擇排序、插入排序。 1.氣泡排序:由陣列頭部開始,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。每次交換完成後,當前陣列最大值就會被放在最後。 1 public int[] bubbleSort 最壞時間複雜度為N^2排序(冒泡-選擇-插入)氣泡排序 public void bubblesort(int a[]) { int len=a.length; int i=len-1; int last=0; while( Manacher演算法,最長迴文串,時間複雜度O(n)最長迴文子串 問題 對於一個字串,請設計一個高效演算法,計算其中最長迴文子串的長度。 給定字串A以及它的長度n,請返回最長迴文子串的長度。 測試樣例: “abc1234321ab”,12 返回:7 中心擴充套件到Manache 將N個字元的陣列,迴圈右移K位。時間複雜度O(N)。將N個字元的陣列,迴圈右移K位。時間複雜度O(N) eg:str[]=”abcde123”,右移3位 1、旋轉abcde->edcba 2、旋轉123->321 3、整體旋轉 時間複雜度O(n)什麼意思時間複雜度O(n)什麼意思 2018年11月29日 14:55:38 Super_King_ 閱讀數:33 標籤: 演算法時間複雜度 更多 個人分類: 後端 時間複雜度 演算法分析 同一問題可用不同演算法 BFPRT演算法:時間複雜度O(n)求第k小的數字(分治演算法+快排)去年寫了一篇《分治演算法 求第 k k k小元素 判斷一個數是不是素數 埃拉託斯特尼篩法 時間複雜度 O(n*lglgn)說明: 素數的定義:質數(prime number)又稱素數。一個大於1的自然數,除了1和它本身外,不能被其他自然數整除,換句話說就是該數除了1和它本身以外不再有其他的因數;否則稱為合數。 最小的素數是2,最小的合數是4 方法一: 根據素數的定義,判斷數n是不是素數,我們 最大子序列的和演算法-時間複雜度O(n)#include<iostream> using namespace std; int MaxSubseqSum(int ar[],int n){ int ThisSum=0,MaxSu php多維陣列的去重(針對任意的鍵值進行去重)--二維陣列的唯一--時間複雜度~O(n)以二維陣列為例,來說明針對任意鍵值的去重,時間複雜度為~O(n),只用一個foreach迴圈: <?php $arr = array( '0'=>array( 1134 最長遞增子序列(時間複雜度O(n*log(n))基準時間限制:1 秒 空間限制:131072 KB 分值: 0 難度:基礎題 Description 給出長度為N的陣列,找出這個陣列的最長遞增子序列。(遞增子序列是指,子序列的元素是遞增的) 例如:5 1 6 8 2 4 5 10,最長遞增 編寫程式,在一非遞減的順序表L中,刪除所有值相等的多餘元素。要求時間複雜度O(n),空間複雜度為O(1)翠花上程式碼: Status delExcrescentValue(SeqList &S){ int flag = 0,val = S.elem[0];//記錄值不等的下標 //printf("%d\n",S.elem[0]); for(int i = 1;i 題目9 單鏈表中儲存M個整數,設計一個時間複雜度儘可能高效的演算法單鏈表中儲存M個整數,設計一個時間複雜度儘可能高效的演算法,對於連結串列中絕對值相等的元素(|data|<n),只保留第一次出現的節點,刪除其餘的節點。如:15->(-3)->(-15)->3 得:15->(-3) |