对数组排序有多种方法,是企业常考察的内容
题目
给你一个整数数组 nums,请你将该数组升序排列。
示例 1:
输入:nums = [5,2,3,1]
输出:[1,2,3,5]
示例 2:
输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]
提示:
1 <= nums.length <= 5 * 104
-5 * 104 <= nums[i] <= 5 * 104
插入排序
思路
插入排序分为已排序元素组成的部分(理解为排好队的人),和现在所指的元素(想要插队的人、队列按身高排序),对于现在所指的元素,如果数值小于(形成从小到大顺序的数组)已排序元素的倒数第一个值(最大值),就继续和已排序元素的倒数第二个值比较,直到已排序元素所指此时已小于他的位置,说明他在已排序元素队列中找到了自己的位置,于是值比他大的元素都在已排序元素数组中自动后移为他让出一个位置,然后再把他的值放(赋值)到这个位置,他就插入到了正确的位置,而已排序数组则长度+1,直到所有数都排入已排序数组,此时我们需要的升序数组就是已排序数组。
代码
//插入排序
class Solution {
public int[] sortArray(int[] nums) {
int len = nums.length;
for(int i = 0;i < len;i ++)
{
int temp = nums[i];//暂存这个元素
int j = i;//数组[0,j]之间属于是已排序部分
//后序元素逐个后移流出空位
while(j > 0 && nums[j-1] > temp)//这里用nums[j-1]是因为nums[j]一开始和nums[i]相等,不会进入循环
//这里的temp不可省去直接用nums[i]替换,
//因为实际上 nums[j] = nums[j-1]会修改nums数组内的值,
//此时访问的nums[i]值未必是赋予temp时的nums[i]值
{
nums[j] = nums[j-1];
j--;
}
nums[j] = temp;
}
return nums;
}
}
快速排序
快排是一种基于递归的算法,采用分治的思想实现。
//快速排序
class Solution {
//下面递归循环中小区间采用插入排序,我们设定一个定值区分这个区间的大小
private static final int INERTION_SORT_THRESHOLD = 7;
private static final Random RANDOM = new Random();
public int[] sortArray(int[] nums)//主函数
{
int len = nums.length;
quickSort(nums,0,len-1);
return nums;
}
private void quickSort(int[] nums,int left,int right)
{
//小区间采用插入排序
if(right - left <= INERTION_SORT_THRESHOLD)
{
insertionSort(nums,left,right);
return;
}
int pIndex = partition(nums,left,right);//pIndex本质上是被随机出来的数,避免遇到原本基本有序的数组导致快排效率太低(与快排越无序越快的特性有关)
quickSort(nums,left,pIndex-1);//左半数组递归采用快排
quickSort(nums,pIndex + 1,right);
}
private void insertionSort(int[] nums, int left, int right)//插入排序的基本实现(参考上面)
{
for(int i = left + 1; i <= right;i++)
{
int temp = nums[i];
int j = i;
while(j > left && nums[j - 1] > temp)
{
nums[j] = nums[j - 1];
j--;
}
nums[j] = temp;
}
}
private int partition(int[] nums, int left, int right)//分界数的获取
{
int randomIndex = RANDOM.nextInt(right - left + 1) + left;
swap(nums, left, randomIndex);
//基准值
int pivot = nums[left];
int lt = left;//lt代表less than的缩写
//pivot满足数组中所有index小于他的数均小于他
//pivot满足数组中所有index大于他的数均大于他
for (int i = left + 1;i <= right; i++)
{
if(nums[i] < pivot)
{
lt++;
swap(nums,i,lt);
}
}
swap(nums,left,lt);
return lt;//最后返回的是数组下标
}
private void swap(int[] nums,int index1,int index2)//交换数组中两个值
{
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
}
}