赞
踩
力扣连接:. - 力扣(LeetCode)
对左右子集合分别排序,然后合并两个有序数组
- class Solution {
- int[] nums;
- public int[] sortArray(int[] nums) {
- this.nums = nums;
- return sort(0, nums.length-1);
- }
-
- int[] sort(int st, int ed) {
- if(st == ed) {
- return new int[]{nums[st]};
- }
- //对左右分别排序
- int m = st + (ed-st)/2;
- int[] leftArr = sort(st, m);
- int[] rightArr = sort(m+1, ed);
-
- //合并两个有序数组
- int[] newArr = new int[ed-st+1];
- int i=0,j=0,k=0;
- while(i<leftArr.length && j<rightArr.length){
- if(leftArr[i]<rightArr[j]){
- newArr[k++]=leftArr[i++];
- }else{
- newArr[k++]=rightArr[j++];
- }
- }
- while(i<leftArr.length) newArr[k++] = leftArr[i++];
- while(j<rightArr.length) newArr[k++] = rightArr[j++];
-
- return newArr;
- }
- }
每次任意指定一个数作为标杆,小于标杆的放左边,大于标杆的放右边,对左右子数组重复这个流程
时间复杂度:O(n log n)
空间复杂度:O(n)
- class Solution {
- int[] nums;
-
- public int[] sortArray(int[] nums) {
- this.nums = nums;
- sort(0, nums.length - 1);
- return nums;
- }
-
- void sort(int st, int ed) {
- if (st >= ed)
- return;
- int p = st, l = st, r = ed;
- while (l < r) {
- // r指向第一个小于等于nums[p]的,注意这和下个while顺序不能随便换,要保证l和r最后指向小于等于nums[p]的地方
- while (l < r && nums[r] > nums[p]) r--;
- // l指向第一个大于nums[p]的
- while (l < r && nums[l] <= nums[p]) l++;
- swap(l, r);
- }
- swap(p, l);
- sort(st, l - 1);
- sort(l + 1, ed);
- }
-
- void swap(int i, int j) {
- int temp = nums[i];
- nums[i] = nums[j];
- nums[j] = temp;
- }
-
- }
时间复杂度:O(nlogn)
视频讲解:排序算法:堆排序【图解+代码】_哔哩哔哩_bilibili
大顶堆:父节点比两个子节点都要大
下标规律:
节点 i 的父节点:(i-1)/2
节点 i 的左子节点:i*2+1
节点i的右子节点:(i+1)*2
维护大顶堆:从下往上,第一个有孩子节点的节点开始,取根节点、左孩子、右孩子之间的最大值 换到根节点处
排序:堆顶的元素一定是最大的,每次将堆顶元素放到尾部,然后剩下元素再次维护大顶堆,重复
- class Solution {
- int[] nums;
- public int[] sortArray(int[] nums) {
- this.nums = nums;
- int len = nums.length;
- sort(len);
- return nums;
- }
-
- void sort(int len) {
- //建堆
- for(int i= len/2-1;i>=0;i--) {
- heapify(len, i);
- }
- //排序
- for(int i=len-1;i>0;i--) {
- swap(i, 0);
- //i以后的数是已经排序好的
- heapify(i, 0);
- }
-
- }
-
- //i: 待维护的节点下标
- //len: 参与维护大顶堆的数组长度
- void heapify(int len, int i) {
- int biggest = i;
- int left = i*2+1;
- int right = (i+1)*2;
- //len用来约束递归终止条件
- if(left<len && nums[biggest]<nums[left]){
- biggest = left;
- }
- if(right<len && nums[biggest]<nums[right]){
- biggest = right;
- }
- if(biggest != i){
- swap(biggest, i);
- heapify(len, biggest);
- }
- }
-
- void swap(int i, int j) {
- int temp = nums[i];
- nums[i] = nums[j];
- nums[j] = temp;
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。