今天主要就做了每日一题
效率太低了,一整天感觉就写了个快速排序和堆排序,都是些基础,也摆弄了挺久。这里讲一下力扣的快速排序官方题解的partition函数是有bug的,不过因为他用了随机快排,所以bug比较难触发,这里记录一下[3,1,1,0,3]这个序列就会触发他的partition的bug,所以还是用模板partition比较稳妥(被这个破bug坑了一个上午),这里记录一下我写的solution。
class Solution {
public int[] sortArray(int[] nums) {
quickSort(nums,0,nums.length-1);
return nums;
}
public int partition(int[] nums, int l, int r){
int pivot = nums[l];
int i=l,j=r;
while(j>i){
while(j>i&&nums[j]>pivot)//注意如果pivot选的是最左边的,就需要从最右边开始,反方向类似
j--;
nums[i] = nums[j];
while(j>i&&nums[i]<=pivot){//这里注意需要等于
i++;
nums[j] = nums[i];
}
}
nums[i] = pivot;
return i;
}
public void quickSort(int[] nums,int l, int r){
if(l < r) {//注意这个l<r的条件,不然数组会越界
int p = partition(nums,l,r);
quickSort(nums,l,p-1);
quickSort(nums,p+1,r);
}
}
}
注意以上有注释的几个点,就可以少出点错。
下面讲一下堆排序,之前对堆排序确实了解的也不多,这次好好学习了一下。
堆排序分为两个过程:
- 创建小根堆
- 不断弹出堆顶元素,进行堆排序
下面看一下我的solution
class Solution {
public int[] sortArray(int[] nums) {
//swap(nums,0,1);
//heapify(nums,0);
int length = nums.length;
heapInit(nums, 0, length);//建立小顶堆
int i=0;
int[] res = new int[nums.length];
while(length>0){
res[i] = pop(nums,length-1);
length--;
i++;
}
return res;
}
//弹出堆顶元素的实现
public int pop(int[] nums,int last){
swap(nums,0,last);//首先交换堆顶元素和最后一个元素
int res = nums[last];//记录堆顶元素
heapify(nums,0,last);//对堆顶进行一次heapify,因为下面的树都是符合小顶堆的,所以一次heapify就可以了
return res;
}
public void swap(int[] nums, int i, int j){//为了方便实现的swap
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public void heapify(int[] nums,int n, int l) {
if(n>=nums.length) return;
//找到两个孩子节点
int c1 = n*2 + 1;
int c2 = n*2 + 2;
//找到最小的元素并且换到堆顶
int min = n;
if((c1 < l) && (nums[c1] < nums[min])) {//注意孩子节点的下标不要越界
min = c1;
//System.out.println(nums[0]);
}
if((c2 < l) && (nums[c2] < nums[min])) {
min = c2;
//System.out.println(nums[0]);
}
//换好元素之后,再对被换下来的位置进行heapify,一直递归往下,直到遇到一个符合小顶堆的子树为止
if(min != n) {
swap(nums,min,n);
heapify(nums, min, l);
}
}
public void heapInit(int[] nums, int n, int l){//生成小顶堆
int lastNode = (l - 1) / 2;
//直接对从最后一个非叶节点开始,按顺序对所有非叶节点进行一次heapify
for(int i = lastNode;i>=0;i--){
heapify(nums, i, l);
}
}
}
这并不是标准的实现,标准的堆排序应该是用递归实现,因为偷了下懒,而且这样实现也更加直观。