對於求乙個陣列中第k小的數, 可以用快速排序的中間過程解決, 例如 找到的基準數的位置》k, 這時候就只需要對於前半部分再進行行 一次這個中間過程.直到找到 第k個數.
然而問題是,快速排序的基準數如果選的不好,範圍就縮小不了1/2甚至還沒有, 時間複雜度可能會到o(n^2).
所以 關於 選擇基準數 可以不隨機選,而是通過如下步驟:
[1] 將陣列每5個分成一組, 可能最後一組不足5個
[2] 進行組內排序, 因為對5個進行排序的時間複雜度可以看成o(1), 所以總消耗o(n).
[3] 將每一組的中位數提取出來形成乙個新的陣列, 這個新的陣列的長度是1 + n/5, 然後對這個新陣列 再進行[1][2][3]步驟, 不過是找這個中位數陣列的1/2位置的元素. 得到它之後,
[4] 利用得到的中位數陣列的第1/2個數作為基準, 進行快速排序的part過程
對組內排序進行分析, 一開始是o(n) , 遞迴呼叫是 o(n/5) , o(n/25) ... 這個是趨於o(n)的, 然而有空間消耗
/**
* 找出陣列中第k小數字
* @param arr
* @param k 從0開始計數 [0, arr.len-1]
* @return
*/public int bfprt(int arr, int k, int left, int right) else if (right - left <= 0)
final int z = 5;
// 每5個一組, 組內排序
sortforgroup(arr, z, left, right);
// 抽取中位數, 組成乙個新陣列
int newarr = new int[(right - left) / 5 + 1];
getmidnumberformgroup(arr, z, newarr, left, right);
int midvalue = bfprt(newarr, newarr.length / 2 , 0, newarr.length - 1);
int ret = part(arr, 0, arr.length-1, midvalue);
if (ret[0] >= k && ret[1] <= k) else if (k < ret[0]) else
}private void getmidnumberformgroup(int arr, int z, int midarr, int left, int right) else }}
private void sortforgroup(int arr, int z, int left, int right)
arrays.sort(arr, i, j + 1);}}
/*** 這個是快速排序part的過程, base 必須是[left, right]之內的數
* 如果base==null, 隨機去乙個作為基數
* 返回的陣列 ret[0] 是 第乙個等於base的索引位置, ret[1]是最後乙個等於base的索引位置
* @param arr
* @param left
* @param right
* @param base
* @return
*/public int part(int arr, int left, int right, integer base)
threadlocalrandom random = threadlocalrandom.current();
int realbase = (base == null)? arr[left + random.nextint(right - left + 1)] : base;
int lt = left - 1, gt = right;
int i = left;
while (i <= gt) else if (arr[i] > realbase) else
}return new int ;
}public void change(int arr, int i, int j)
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
對KMP演算法理解
kmp演算法是一種在乙個字串中匹配另乙個字串的高效演算法。簡單字元的匹配演算法時間複雜度為o m n kmp演算法的時間複雜度為o m n 下面是我在vs上的求next值驗證演算法。include abc.h include using namespace std int main unsigned...
A 演算法理解
廣度優先 bfs 和深度優先 dfs 搜尋 深度優先搜尋,用俗話說就是不見棺材不回頭。演算法會朝乙個方向進發,直到遇到邊界或者障礙物,才回溯。一般在實現的時候,我們採用遞迴的方式來進行,也可以採用模擬壓棧的方式來實現。如下圖,s代表起點,e代表終點。我們如果按照右 下 左 上這樣的擴充套件順序的話,...
我對遺傳演算法理解
1 始祖值 2 隨機交叉 3 優秀標準 4 精英策略 5 收斂 始祖值,a 1 echo print r a echo 雜湊值 any array 2,4,7,8,10,12,51,32,11 echo print r any echo 交叉並啟動精英策略,假設後代的和越大越優秀 foreach a...