quickSort
快排在于一次把所有【大于pivot的值和小于pivot的值】都交換了润文,所以要用到while,用left和right指針控制交換的元素
public class Solution {
public void sortIntegers2(int[] A) {
// write your code here
if (A == null || A.length == 0) {
return;
}
quickSort(A, 0, A.length - 1);
}
private void quickSort(int[] A, int start, int end) {
//遞歸出口 沒(méi)有這個(gè)會(huì)爆棧,因?yàn)槌霾粊?lái)了
//注意是 >=, 其實(shí)>在quickSort里也可以因?yàn)槭莑eft++,right--是一個(gè)一個(gè)移動(dòng)的
//而mergeSort用mid = (start + end) / 2控制,涉及了舍位
if (start >= end) {
return;
}
int left = start;
int right = end;
int pivot = A[(start + end) / 2];
// pivot兩邊等于也要交換,避免效率低下
while (left <= right) {
while (left <= right && A[left] < pivot) {
left++;
}
while (left <= right && A[right] > pivot) {
right--;
}
//時(shí)刻記住left <= right缺亮,而且是if條件,因?yàn)榻?jīng)過(guò)上面的while loop,兩個(gè)交錯(cuò)是很有可能
if (left <= right) {
int temp = A[left];
A[left] = A[right];
A[right] = temp;
left++;
right--;
}
}
quickSort(A, start, right);
quickSort(A, left, end);
}
}
quickSeleck(找第K大元素)
class Solution {
/*
* @param k : description of k
* @param nums : array of nums
* @return: description of return
*/
public int kthLargestElement(int k, int[] nums) {
// qucik select
if (nums == null || nums.length < k) {
return 0;
}
//nums.length的話(huà)數(shù)組越界
return quickSelect(nums, 0, nums.length - 1, k);
}
private int quickSelect(int[] nums, int start, int end, int k) {
//出口
if (start == end) {
return nums[start];
}
int i = start, j = end;
int pivot = nums[(start + end) / 2];
//當(dāng)這個(gè)循環(huán)退出的時(shí)候一定是i > j
while (i <= j) {
while (i <= j && nums[i] > pivot) {
i++;
}
while (i <=j && nums[j] < pivot) {
j--;
}
if (i <= j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++;
j--;
}
}
//這里這里桥言,從while循環(huán)出來(lái)時(shí)萌踱,j < i 了
//.....j?i....OR .....ji.....
//j和i中間有可能有 有可能沒(méi)有
//這里的k - 1是帶數(shù)帶出來(lái)的假設(shè)start = j,都進(jìn)這個(gè)條件了葵礼,肯定是找這個(gè)區(qū)間第一大的數(shù),即k = 1并鸵,但是start + k = j的話(huà),左右兩邊去掉start和j得出k = 0鸳粉,與假設(shè)不符,所以說(shuō) 判斷條件是start + k - 1 <= j
//還有一種(k - 1)的解釋方法:因?yàn)镵并不是zero-based,而start 是zero-based,所以需要k - 1; 如果k是zero-based园担,那么就是start + k <= j
if (start + k - 1 <= j) {
return quickSelect(nums, start, j, k);
}
if (start + k - 1 >= i) {
//start i
//1234567|8
//從1到8有(8 - 1 + 1 = 8)個(gè)數(shù)届谈,而8前面有8 - 1 = 7個(gè)數(shù)
return quickSelect(nums, i, end, k - (i - start));
}
//這里屬于這種情況.....j?i....
return nums[j + 1];
}
};
mergeSort
public class Solution {
/*
* @param A: an integer array
* @return:
*/
public void sortIntegers2(int[] A) {
if (A == null || A.length == 0) {
return;
}
int[] temp = new int[A.length];
mergeSort(A, 0, A.length - 1, temp);
}
private void mergeSort(int[] A, int start, int end, int[] temp) {
//遞歸出口
//而且一定要是>=就退出, 因?yàn)橛肕iddle控制了start和end
//mid涉及了舍位的問(wèn)題
if (start >= end) {
return;
}
//思考 為什么這里就不需要start和end賦給left和right
int middle = (start + end) / 2;
int right = middle + 1;
mergeSort(A, start, middle, temp);
mergeSort(A, right, end, temp);
merge(A, start, end, temp);
}
private void merge(int[] A, int start, int end, int[] temp) {
//思考 為什么這里需要start和end賦給left和right
int left = start;
int middle = (start + end) / 2;
int right = middle + 1;
//因?yàn)槭沁f歸 所以要從遞歸的角度考慮初始值
int index = start;
while (left <= middle && right <= end) {
if (A[left] < A[right]) {
temp[index++] = A[left++];
} else {//這里包含了等于的情況
temp[index++] = A[right++];
}
}
while (left <= middle) {
temp[index++] = A[left++];
}
while (right <= end) {
temp[index++] = A[right++];
}
//因?yàn)槭沁f歸 所以要從遞歸的角度考慮賦值范圍, 這里是i <= end, start和end都要copy到temp[]里面
for (int i = start; i <= end; i++) {
A[i] = temp[i];
}
}
}