赞
踩
题目:
给你一个整数数组 nums
,请你将该数组升序排列。
示例 1:输入:nums = [5,2,3,1] 输出:[1,2,3,5]
1、直接插入排序
- /*nums[]数组,对其升序排序
- * */
- //插入排序
- public class InsertSort {
- public int[] sortArray(int[] nums) {
- int len = nums.length;
- for (int i = 1; i < len; i++) {
- // 先暂存这个元素,然后之前元素逐个后移,留出空位
- if (nums[i]<nums[i-1]) {
- int temp = nums[i];
- int j = i - 1;
- while (j >= 0 && nums[j] > temp) {
- nums[j + 1] = nums[j];
- j--;
- }
- nums[j + 1] = temp;
- }
- }
- return nums;
- }
-
-
- }

2、选择排序
- public class Solution {
-
- // 选择排序:每一轮选择最小元素交换到未排定部分的开头
-
- public int[] sortArray(int[] nums) {
- int len = nums.length;
- // 循环不变量:[0, i) 有序,且该区间里所有元素就是最终排定的样子
- for (int i = 0; i < len - 1; i++) {
- // 选择区间 [i, len - 1] 里最小的元素的索引,交换到下标 i
- int minIndex = i;
- for (int j = i + 1; j < len; j++) {
- if (nums[j] < nums[minIndex]) {
- minIndex = j;
- }
- }
- swap(nums, i, minIndex);
- }
- return nums;
- }
-
- private void swap(int[] nums, int index1, int index2) {
- int temp = nums[index1];
- nums[index1] = nums[index2];
- nums[index2] = temp;
- }
-
- public static void main(String[] args) {
- int[] nums = {5, 2, 3, 1};
- Solution solution = new Solution();
- int[] res = solution.sortArray(nums);
- System.out.println(Arrays.toString(res));
- }
- }

3、归并排序
- public class Solution {
- // 归并排序
-
- /**
- * 列表大小等于或小于该大小,将优先于 mergeSort 使用插入排序
- */
- private static final int INSERTION_SORT_THRESHOLD = 7;
-
- public int[] sortArray(int[] nums) {
- int len = nums.length;
- int[] temp = new int[len];
- mergeSort(nums, 0, len - 1, temp);
- return nums;
- }
-
- /**
- * 对数组 nums 的子区间 [left, right] 进行归并排序
- *
- * @param nums
- * @param left
- * @param right
- * @param temp 用于合并两个有序数组的辅助数组,全局使用一份,避免多次创建和销毁
- */
- private void mergeSort(int[] nums, int left, int right, int[] temp) {
- // 小区间使用插入排序
- if (right - left <= INSERTION_SORT_THRESHOLD) {
- insertionSort(nums, left, right);
- return;
- }
-
- int mid = left + (right - left) / 2;
- // Java 里有更优的写法,在 left 和 right 都是大整数时,即使溢出,结论依然正确
- // int mid = (left + right) >>> 1;
- mergeSort(nums, left, mid, temp);
- mergeSort(nums, mid + 1, right, temp);
- // 如果数组的这个子区间本身有序,无需合并
- if (nums[mid] <= nums[mid + 1]) {
- return;
- }
- mergeOfTwoSortedArray(nums, left, mid, right, temp);
- }
-
- /**
- * 对数组 arr 的子区间 [left, right] 使用插入排序
- *
- * @param arr 给定数组
- * @param left 左边界,能取到
- * @param right 右边界,能取到
- */
- private void insertionSort(int[] arr, int left, int right) {
- for (int i = left + 1; i <= right; i++) {
- int temp = arr[i];
- int j = i;
- while (j > left && arr[j - 1] > temp) {
- arr[j] = arr[j - 1];
- j--;
- }
- arr[j] = temp;
- }
- }
-
- /**
- * 合并两个有序数组:先把值复制到临时数组,再合并回去
- *
- * @param nums
- * @param left
- * @param mid [left, mid] 有序,[mid + 1, right] 有序
- * @param right
- * @param temp 全局使用的临时数组
- */
- private void mergeOfTwoSortedArray(int[] nums, int left, int mid, int right, int[] temp) {
- System.arraycopy(nums, left, temp, left, right + 1 - left);
-
- int i = left;
- int j = mid + 1;
-
- for (int k = left; k <= right; k++) {
- if (i == mid + 1) {
- nums[k] = temp[j];
- j++;
- } else if (j == right + 1) {
- nums[k] = temp[i];
- i++;
- } else if (temp[i] <= temp[j]) {
- // 注意写成 < 就丢失了稳定性(相同元素原来靠前的排序以后依然靠前)
- nums[k] = temp[i];
- i++;
- } else {
- // temp[i] > temp[j]
- nums[k] = temp[j];
- j++;
- }
- }
- }
- }

4、快速排序
- import java.util.Random;
-
- public class Solution {
-
- // 快速排序 2:双指针(指针对撞)快速排序
-
- /**
- * 列表大小等于或小于该大小,将优先于 quickSort 使用插入排序
- */
- private static final int INSERTION_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 <= INSERTION_SORT_THRESHOLD) {
- insertionSort(nums, left, right);
- return;
- }
-
- int pIndex = partition(nums, left, right);
- quickSort(nums, left, pIndex - 1);
- quickSort(nums, pIndex + 1, right);
- }
-
- /**
- * 对数组 nums 的子区间 [left, right] 使用插入排序
- *
- * @param nums 给定数组
- * @param left 左边界,能取到
- * @param 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 = left + RANDOM.nextInt(right - left + 1);
- swap(nums, randomIndex, left);
-
- int pivot = nums[left];
- int lt = left + 1;
- int gt = right;
-
- // 循环不变量:
- // all in [left + 1, lt) <= pivot
- // all in (gt, right] >= pivot
- while (true) {
- while (lt <= right && nums[lt] < pivot) {
- lt++;
- }
-
- while (gt > left && nums[gt] > pivot) {
- gt--;
- }
-
- if (lt >= gt) {
- break;
- }
-
- // 细节:相等的元素通过交换,等概率分到数组的两边
- swap(nums, lt, gt);
- lt++;
- gt--;
- }
- swap(nums, left, gt);
- return gt;
- }
-
- private void swap(int[] nums, int index1, int index2) {
- int temp = nums[index1];
- nums[index1] = nums[index2];
- nums[index2] = temp;
- }
- }

5、堆排序
- public class Solution {
-
- public int[] sortArray(int[] nums) {
- int len = nums.length;
- // 将数组整理成堆
- heapify(nums);
-
- // 循环不变量:区间 [0, i] 堆有序
- for (int i = len - 1; i >= 1; ) {
- // 把堆顶元素(当前最大)交换到数组末尾
- swap(nums, 0, i);
- // 逐步减少堆有序的部分
- i--;
- // 下标 0 位置下沉操作,使得区间 [0, i] 堆有序
- siftDown(nums, 0, i);
- }
- return nums;
- }
-
- /**
- * 将数组整理成堆(堆有序)
- *
- * @param nums
- */
- private void heapify(int[] nums) {
- int len = nums.length;
- // 只需要从 i = (len - 1) / 2 这个位置开始逐层下移
- for (int i = (len - 1) / 2; i >= 0; i--) {
- siftDown(nums, i, len - 1);
- }
- }
-
- /**
- * @param nums
- * @param k 当前下沉元素的下标
- * @param end [0, end] 是 nums 的有效部分
- */
- private void siftDown(int[] nums, int k, int end) {
- while (2 * k + 1 <= end) {
- int j = 2 * k + 1;
- if (j + 1 <= end && nums[j + 1] > nums[j]) {
- j++;
- }
- if (nums[j] > nums[k]) {
- swap(nums, j, k);
- } else {
- break;
- }
- k = j;
- }
- }
-
- private void swap(int[] nums, int index1, int index2) {
- int temp = nums[index1];
- nums[index1] = nums[index2];
- nums[index2] = temp;
- }
- }
-

6、希尔排序
- public class Solution {
-
- // 希尔排序
-
- public int[] sortArray(int[] nums) {
- int len = nums.length;
- int h = 1;
-
- // 使用 Knuth 增量序列
- // 找增量的最大值
- while (3 * h + 1 < len) {
- h = 3 * h + 1;
- }
-
- while (h >= 1) {
- // insertion sort
- for (int i = h; i < len; i++) {
- insertionForDelta(nums, h, i);
- }
- h = h / 3;
- }
- return nums;
- }
-
- /**
- * 将 nums[i] 插入到对应分组的正确位置上,其实就是将原来 1 的部分改成 gap
- *
- * @param nums
- * @param gap
- * @param i
- */
- private void insertionForDelta(int[] nums, int gap, int i) {
- int temp = nums[i];
- int j = i;
- // 注意:这里 j >= deta 的原因
- while (j >= gap && nums[j - gap] > temp) {
- nums[j] = nums[j - gap];
- j -= gap;
- }
- nums[j] = temp;
- }
- }
-

7、冒泡排序
- public class Solution {
-
- // 冒泡排序:超时
-
- public int[] sortArray(int[] nums) {
- int len = nums.length;
- for (int i = len - 1; i >= 0; i--) {
- // 先默认数组是有序的,只要发生一次交换,就必须进行下一轮比较,
- // 如果在内层循环中,都没有执行一次交换操作,说明此时数组已经是升序数组
- boolean sorted = true;
- for (int j = 0; j < i; j++) {
- if (nums[j] > nums[j + 1]) {
- swap(nums, j, j + 1);
- sorted = false;
- }
- }
- if (sorted) {
- break;
- }
- }
- return nums;
- }
-
- private void swap(int[] nums, int index1, int index2) {
- int temp = nums[index1];
- nums[index1] = nums[index2];
- nums[index2] = temp;
- }
- }
-

8、折半排序
- public class BinaryInsertSortTest {
- public void binaryInsertSort(int[] data) {
- for (int i = 1; i < data.length; i++) {
- if (data[i] < data[i - 1]) {
- // 缓存i处的元素值
- int tmp = data[i];
- // 记录搜索范围的左边界
- int low = 0;
- // 记录搜索范围的右边界
- int high = i - 1;
- while (low <= high) {
- // 记录中间位置
- int mid = (low + high) / 2;
- // 比较中间位置数据和i处数据大小,以缩小搜索范围
- if (data[mid] < tmp) {
- low = mid + 1;
- } else {
- high = mid - 1;
- }
- }
- //将low~i处数据整体向后移动1位
- for (int j = i; j > low; j--) {
- data[j] = data[j - 1];
- }
- data[low] = tmp;
- }
- }
- }

题目链接:力扣
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。