- 题目:用时间复杂度为o(nlogn)的算法,给定一个未排序的整数数组,找到其中位数。中位数是排序后数组的中间值,如果数组的个数是偶数个,则返回排序后数组的第N/2个数。
- 难度:Easy
- 思路:利用快排,pivot存放的位置index,如果index=(N-1)/2,说明pivot前面有index个元素小于或者pivot,每次递归快排,判断index的值与(N-1)/2的大小关系
- 代码:
这里的快排是直接用数组待排序的数组序列的第一个元素作为枢纽元素
public class Solution {
/**
* @param nums: A list of integers.
* @return: An integer denotes the middle number of the array.
*/
public int median(int[] nums) {
// write your code here
if(nums == null || nums.length == 0){
return 0;
}
int len = nums.length;
if(len == 1){
return nums[0];
}
return quickSort(nums, 0, len-1);
}
public int quickSort(int[] nums, int start, int end){
int pivot = nums[start];//取数组中第一个元素为枢纽
int i = start; int j = end;
if(start < end){
while(i < j){
System.out.println(i + "-" + j);
while(i < end && nums[i] <= pivot){
i++;
}
while(j > start && nums[j] >= pivot){
j--;
}
if(i < j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}else{
break;
}
}
if(pivot > nums[j]){
nums[start] = nums[j];
nums[j] = pivot;
}//这里的交换,需要先判断pivot和nums[j]的大小(因为枢纽元素是start位置,所以需要与j位置的进行判断并交换)
//找到pivot存在的位置j,这里是j位置作为枢纽的存放位置,所以判断j与(N-1)/2的大小关系
if(j == (nums.length-1)/2){
return nums[j];
}else if(j < (nums.length-1)/2){
return quickSort(nums, j+1, end);
}else{
return quickSort(nums, start, j-1);
}
}else{
return nums[start];
}
}
}
这一道题目,让我对快排又有了重新的认识,以前看书上快排的伪代码,觉得理解得很好了,但是这次用快排来解决问题的时候,自己手写快排,发现快排远不止我想象的简单。
值得注意的细节有:
枢纽元素的位置选择,直接影响后面进行枢纽元素在数组中的最终位置
- 题目中我选择的枢纽元素位置是待排序序列的首部,那最后进行比较并且交换的位置就是j位置
- 书上给的伪代码,枢纽元素位置是在待排序序列的倒数第二个,然后用i位置的值和枢纽比较并且交换
这一步是将枢纽元素在数组中的位置确定
继续下一次快排调用中的start位置和end位置的确定
- 如果第1点中,与枢纽元素交换的是j位置的值,那么就以j为分界,将数组分为两部分进行快排