文章目录

前言

除了去年11月份以及今年近几月的算法刷题之外,只有在当时20年蓝桥杯准备的时候才刷过一些题,在当时就有接触到一些动归、递归回溯、贪心等等,不过那会也还是一知半解,做的题目也特别少,因为考虑到之后面试有算法题以及数据结构算法对于一个程序员十分重要,我也开始了刷题之路。

我目前的学习数据结构与算法及刷题路径:

1、学习数据结构的原理以及一些常见算法。

2、​​代码随想录​​:跟着这个github算法刷题项目进行分类刷,在刷题前可以学习一下对应类别的知识点,而且这里面每道题都讲的很详细。

3、牛客网高频面试101题:​​牛客网—面试必刷101题​​,在刷的过程中可以在leetcode同步刷一下。

4、接下来就是力扣上的专栏​​《剑指offer II》​​​、​​《程序员面试金典(第 6 版)》​​…有对应的精选题单来对着刷即可。

5、大部分的高频面试、算法题刷完后,就可以指定力扣分类专栏进行一下刷题了。

刚开始刷的时候真的是很痛苦的,想到去年一道题可能就需要好几小时,真的就很难受的,不过熬过来一切都会好起来,随着题量的增多,很多题目你看到就会知道使用什么数据结构或者算法来去求解,并且思考对应的时间空间复杂度,并寻求最优解,我们一起加油!

我的刷题历程

截止2022.8.18:

1、牛客网101题(其中1题是平台案例有问题):

10数据结构与算法刷题之【排序算法】篇_排序算法

2、剑指offerII:

10数据结构与算法刷题之【排序算法】篇_排序算法_02

力扣总记录数:

10数据结构与算法刷题之【排序算法】篇_排序算法_03

加油加油!

牛客网

寻找第K大【中等】

题目链接:​​寻找第K大​

题目内容:有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。

最佳思路:快排+二分+随机基准点。在快排的过程中不断的找到对应的基准点,然后以这个基准点比较k(基准点的左边是>该基准点的,这样我们才能将基准点的索引与第k大的索引来进行比较)

思路:快排+二分+随机基准点

复杂度分析:

  • 时间复杂度:O(n.logn)
  • 空间复杂度:O(n)

一个探索思路的过程:

import java.util.*;

public class Solution {

private static int res;
Private static Random random = new Ramdom();

public int findKth(int[] a, int n, int K) {
quickSort(a, 0, n - 1, K);
return res;
}

public void quickSort(int[] a, int l, int r, int K) {
if (l > r) {
return;
}
int mid = partition(a, l, r);
//看这个基准点与K的位置是否相符
if (mid + 1 == K) {
res = a[mid];
}else if (mid + 1 < K) {
quickSort(a, mid + 1, r, K);
}else {
quickSort(a, 0, mid - 1, K);
}
}

public int partition(int[] a, int l, int r) {
int x = Math.abs(random.nextInt()) % (r - l + 1) + l;
swap(a, l, x);
int j = l;
for (int i = l + 1; i <= r; i++) {
if (a[i] >= a[l]) {
j++;
swap(a, i, j);
}
}
//交换基准点
swap(a, l, j);
return j;
}

public void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

}

不同的分块思路:

//方式一:
public int partition(int[] a, int l, int r) {
int x = Math.abs(random.nextInt()) % (r - l + 1) + l;
swap(a, l, x);
int j = l;
for (int i = l + 1; i <= r; i++) {
if (a[i] >= a[l]) {
j++;
swap(a, i, j);
}
}
//交换基准点
swap(a, l, j);
return j;
}

//方式二:
public int partition(int[] a, int l, int r) {
int v = a[l];
int i = l + 1;
int j = r;
while (true) {
//目标找到小于基准值的
while (i <= r && a[i] > v ) {
i++;
}
//目标找到大于基准值的
//注意:这里j>=l+1
while (j >= l + 1 && a[j] < v) {
j--;
}
if (i > j) {
break;
}
swap(a, i, j);
i++;
j--;
}
//交换基准点
swap(a, l, j);
return j;
}