题目地址:https://leetcode-cn.com/problems/sort-an-array/submissions/
github code :https://github.com/javartisan/edx-ds/blob/master/src/main/java/com/javartisan/leetcode/Solution912.java
答案1:快速排序
class Solution { public int[] sortArray(int[] nums) { sort(nums,0,nums.length-1); return nums; } public static void sort(int[] nums,int start,int end){ if(start>=end){ return; } int midIndex = partition(nums,start,end); sort(nums,start,midIndex-1); sort(nums,midIndex+1,end); } // 退出时候 start=end public static int partition(int[] nums,int start,int end){ int midValue=nums[start]; while(start<end){ while(nums[end]>=midValue && start < end){ end--; } nums[start]=nums[end]; while(nums[start]<=midValue && start < end){ start++; } nums[end] =nums[start];; } nums[end] =midValue; return start; } }
答案2:冒泡排序,case 9 数组长度:50000 就超时了
class Solution { public int[] sortArray(int[] nums) { bubble(nums); return nums; } public void bubble(int[] nums){ boolean isHasChange = true; for(int i=nums.length-1;i >= 0&&isHasChange;i--){ isHasChange = false; for(int j=0;j<i;j++){ if(nums[j]>nums[j+1]){ int tmp =nums[j]; nums[j]=nums[j+1]; nums[j+1]=tmp; isHasChange=true; } } } } }
方案3: 选择排序依旧无法通过case 9
// 选择排序是在候选集中选择最小的放到前面 public static void selectSort(int[] nums){ for (int i=0 , size = nums.length; i < size ; i++) { int min = i; for (int j = i;j < size ; j++ ) { if(nums[j]<nums[min]){ min = j; } } if(min==i){ continue; } int tmp = nums[i]; nums[i] =nums[min]; nums[min] =tmp; } }
方案4:
插入排序 可以通过 V1
// 假定前面序列是有序的,后面元素逐渐插入到前面元素即可 public static void insertSort(int[] nums){ for (int i=0,size = nums.length-1; i<size ; i++ ) { int waitToInsertIndex = i+1 ; for (int j =0 ; j<=i ; j++ ) { if(nums[waitToInsertIndex]<nums[j]){ int waitToInsertValue = nums[waitToInsertIndex] ; for (int k =waitToInsertIndex; k>j ; k-- ) { nums[k]=nums[k-1]; } nums[j]=waitToInsertValue; break; } } } }
插入insertV2
// 假定前面序列是有序的,后面元素逐渐插入到前面元素即可 // 对于插入位置使用二分查找 ,但是实际效果并不明显,当找到插入位置之后还有要将插入位置后面的部门元素后移一个位置 // 如果边找边移动效率会高 public static void insertSortV2(int[] nums){ for (int i=0,size = nums.length-1; i<size ; i++ ) { int waitToInsertIndex = i+1 ; int waitToInsertValue =nums[waitToInsertIndex]; int insertIndex = findInsertIndex(nums,nums[waitToInsertIndex],0,i); // 移动元素 insertIndex = insertIndex<0?0:insertIndex; for (int j = waitToInsertIndex;j >insertIndex; j-- ) { nums[j]=nums[j-1]; } // insert nums[insertIndex] =waitToInsertValue; } } /** * * */ public static int findInsertIndex(int[] nums,int value,int start,int end){ while(start< end){ int mid = (start+end) >>1; if(nums[mid]==value){ return mid + 1; }else if(nums[mid]>value){ end=mid-1; }else{ start = mid+1; } } // 找不到时候,如果目标值大于结束index则返回index+1,否则返回index return value>nums[start]?start+1:start; }
插入V3:
// 插入排序三个版本中效率最高的版本 public static void insertSortV3(int[] nums){ for (int i=0,size = nums.length-1; i < size ; i++ ) { //边查找insert位置边移动元素 int waitToInsertValue =nums[i+1]; int j =i; for (; j>=0 ;j--) { if(nums[j]<waitToInsertValue){ break; }else{ nums[j+1] = nums[j]; } } nums[j+1] = waitToInsertValue; } }
版本1:遍历有序子数组查找insert位置然后再次遍历移动元素最终插入。
版本2:使用二分查找插入位置之后再遍历移动元素最终插入,这种方案看似效率提升,实际不明显,插入排序主要性能损耗还是移动元素。
版本3:边移动元素边查找插入位置。 效率最高!