分享会
这周学习的内容
通过代码随想录提供的算法讲解和刷题顺序,这周学习到了很多算法知识。
二分查找:
在一个元素排列有序的数组中,二分查找是比遍历数组更加有效率的做法。通过不断比较数组中间下标的值,来确定目标值再左边的子数列还是右边的子数列,不断缩小目标区间,从而定义目标值的位置。
双指针法(快慢指针法):
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作,提高代码的运行效率。
很多数组和链表的操作都需要双指针的帮助。
例如,要删除数组中值为 val 的元素,你可能会再建一个数组取存放哪些值不等于 val 的元素;如果题目还要你再原数组上完成操作,你可能还要在for循环中嵌套一个for循环,这样代码的时间复杂度会增加,可能导致运行超时。
快指针遍历数组,找到值不等于 val 的元素赋给慢指针,慢指针在得到值后才前进,只用一个for循环就能解决问题。
螺旋矩阵问题:
在碰到螺旋矩阵时,一定要明确好边界的问题,尤其是边上的四个角,它们同时属于两个边界,所以一定要分好它们的归属问题。
顺时针上右下左,逆时针上左下右,尽量按顺序遍历数组,避免出错。
滑动窗口:
它的实现类似于双指针,两个指针一个确定窗口的起始位置,一个确定窗口的终止位置,通常用于寻找数组中满足某个条件的最大或最小子数列。
快速排序:
单趟排序通过将数组最右边设为基准值,从右往左的指针寻找小于基准值的数,从左往右的指针寻找大于基准值的数,二者交换,知道两个指针相遇,将两个指针相遇的位置的值与基准值呼唤,返回基准值互换后的坐标。
然后以该坐标为断点,将数组二分,然后不断递归,直到传入函数的左下标大于右下标,函数开始返回。
或者,在 #include <stdlib.h> 中有一个快排函数 qsort ,我们只需要自定义一个强制类型转换函数,就可以让它帮我们排序。
int cmp_int(const void* _a, const void* _b)
{
int* a = (int*)_a; //强制类型转换
int* b = (int*)_b;
return *a - *b;
}
使用格式为 qsort(数组名, 数组元素个数, 数组每个元素所占的字节的大小, 自定义函数);
链表相交的结点的查找和环形链表的判断与进入环形链表的结点的查找。
遇到的问题
螺旋数组:
在nn阶的螺旋数组中,我的遍历它的代码没有问题,但是同样的代码放在mn阶的螺旋数组中,它的值就会出错,为什么?
假如螺旋数组为3行4列,当我遍历完到第二行时,我就已经将数组遍历完了,但是它的运行却并没有停下。它不会再遍历左右两边的数,但是他会再去遍历底边的数,因为你坐标的值还是小于或等于右边的值,他会再遍历一次数组的底边。
解决方法是再遍历上边和右边后,在遍历下边和右边之前,判断左下标是否大于右下标,或上下标是否大于下下标。
指针:
Leetcode传给你的指针没有虚拟头节点,我们不能直接将其当成我们自己写的带有虚拟头节点的链表那样操作。
移除链表元素、交换链表元素等操作都需要在前一个结点进行操作,如果不注意,很容易弄错操作的元素。
dfs深度搜索非常复杂,加上Leetcode需要自己申请数组空间并返回数组的各项长度,再加上复杂的递归,很难理解。
下周的学习目标
哈希表、栈与队列