leetcode-数组篇
个人理解:算法,涉及到数据结构和解决问题思想的,以及常用的解决方法,
数据结构:无非就是数组,链表,树,图等等
思想:dp,贪心等等
方法:排序,搜索等等
本篇主要介绍: 排序
借助leetcode的215题介绍六种常见好理解的排序思想
/**
* Find the kth largest element in an unsorted array. Note that it is the kth
* largest element in the sorted order, not the kth distinct element.
*
*/
public class Lc215 {
/**
* 常规解题思路:排序
*
* @param nums
* @param k
* @return
*/
public static int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
/**
* 插入排序1 直接插入排序: 直接遍历所有的元素和以前排好的元素比较,如果选择的元素小与之前的元素就替换,直到所有的元素比较过
*
* @param nums
* @param k
* @return
*/
public static int findKthLargest1(int[] nums, int k) {
for (int i = 1; i < nums.length; i++) {
for (int j = i - 1; j > -1; j--) {
if (nums[j] > nums[j + 1]) {
int temp = 0;
temp = nums[j + 1];
nums[j + 1] = nums[j];
nums[j] = temp;
}
}
}
return nums[nums.length - k];
}
/**
* 插入排序2 在直接插入排序的基础上增加控制增量,逻辑上将数组分组,轮流对每一个数组排序
* 希尔排序:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。 大白话:
*/
public static int findKthLargest2(int[] nums, int k) {
// 控制步长
for (int gap = nums.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < nums.length; i++) {
for (int j = i; j >= gap && nums[j] < nums[j - gap]; j -= gap) {
int temp = nums[j];
nums[j] = nums[j - gap];
nums[j - gap] = temp;
}
}
}
return nums[nums.length - k];
}
/**
* 选择排序:在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
*
* @param nums
* @param k
* @return
*/
public static int findKthLargest3(int[] nums, int k) {
for (int i = 0; i < nums.length; i++) {
int index = i;
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] < nums[index]) {
index = j;
}
}
int temp = nums[index];
nums[index] = nums[i];
nums[i] = temp;
}
return nums[nums.length - k];
}
/**
* 交换排序之冒泡排序:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
*
* @param nums
* @param k
* @return
*/
public static int findKthLargest4(int[] nums, int k) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] > nums[j]) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
syso(nums);
}
return nums[nums.length - k];
}
/**
* 快速排序:基本思想:(分治)
*
* 1)选择一个基准元素,通常选择第一个元素或者最后一个元素,
*
* 2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
*
* 3)此时基准元素在其排好序后的正确位置
*
* 4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
*
* 快速排序的示例:
*
*
* @param nums
* @param k
* @return
*/
public static int findKthLargest5(int[] nums, int k) {
quickSort(nums, 0, nums.length - 1);
return nums[nums.length - k];
}
private static void quickSort(int[] nums, int low, int high) {
if (low < high) {
// 找寻基准数据的正确索引
int index = getIndex(nums, low, high);
// 进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序
quickSort(nums, 0, index - 1);
quickSort(nums, index + 1, high);
}
}
private static int getIndex(int[] nums, int low, int high) {
// 基准数据
int tmp = nums[low];
while (low < high) {
// 当队尾的元素大于等于基准数据时,向前挪动high指针
while (low < high && nums[high] >= tmp) {
high--;
}
// 如果队尾元素小于tmp了,需要将其赋值给low
nums[low] = nums[high];
// 当队首元素小于等于tmp时,向前挪动low指针
while (low < high && nums[low] <= tmp) {
low++;
}
// 当队首元素大于tmp时,需要将其赋值给high
nums[high] = nums[low];
syso(nums);
}
// 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置
// 由原理部分可以很清楚的知道low位置的值并不是tmp,所以需要将tmp赋值给arr[low]
nums[low] = tmp;
return low; // 返回tmp的正确位置
}
public static void syso(int[] nums) {
for (int n : nums) {
System.out.print(n + "");
}
System.out.println();
}
public static void main(String[] args) {
int[] nums = { 4, 2, 1, 5, 6, 3 };
// System.out.println(findKthLargest(nums, 2));
// System.out.println(findKthLargest1(nums, 2));
// System.out.println(findKthLargest2(nums, 2));
// System.out.println(findKthLargest3(nums, 2));
// System.out.println(findKthLargest4(nums, 2));
System.out.println(findKthLargest5(nums, 2));
}
}
个人拙见 介绍精美的文章很多,但是想要弄懂就要手写,很多细节不手写根本想不到;另外手写的时候不要看例子,要根据算法的思想去写出来。背例子作用不大
这是带图的介绍,可能会有助于理解
阅读 :https://blog.csdn.net/u014231646/article/details/80267468
拓展连接:https://www.cnblogs.com/lixuejian/p/10889991.html