常用算法模板汇总

12 篇文章 1 订阅

一.排序

1.冒泡
每次排序从首元素(图里为左)开始,相邻元素比较,较大者排后,直至最大数排到队尾。然后对未排序部分重复操作。
时间复杂度:最好O(n),最坏O(n^2)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.快排
先从数列中取出一个数作为基准数。分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。再对左右区间重复第二步,直到各区间只有一个数。
时间复杂度:最好O(nlogn),最坏O(n^2)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.数组

1.时间复杂度
在这里插入图片描述
2.
数组是存放在连续内存空间上的相同类型数据的集合;
因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址
注意vector 和 array区别,vector底层实现是array,严格来讲vector是容器,不是数组。数组的元素是不能删的,只能覆盖

3.二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
在这里插入图片描述
在这里插入图片描述
4.双指针法
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
暴力解法时间复杂度:O(n^2) ,双指针时间复杂度:O(n)
常用于数组、链表、字符串的操作。
在这里插入图片描述
题号27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
在这里插入图片描述

题号26. 删除排序数组中的重复项
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
在这里插入图片描述

题号283.移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
在这里插入图片描述
5.滑动窗口(双指针的一种)
根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。
在这里插入图片描述
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,窗口的起始位置设置为数组的起始位置就可以了。
解题的关键在于 窗口的起始位置如何移动,如图所示:
在这里插入图片描述

题号209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
在这里插入图片描述
在这里插入图片描述
6.数组循环

题号59.螺旋矩阵 II
给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]

题号54.螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
输出: [1,2,3,6,9,8,7,4,5]

题号 剑指Offer-29. 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵:
[ [ 1, 2, 3,4 ], [ 5, 6,7,8 ], [ 9, 10, 11,12 ], [13,14,15,16] ]
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

通用解法如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三.链表

1.虚拟头节点

题号203.移除链表元素
题意:删除链表中等于给定值 val 的所有节点。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
在这里插入图片描述
注:(此处的node其实是链表的head节点)
dummyhead->next= node dummyhead指针指向node;
listnode* cur = dummyhead->next cur指向dummyhead的下个节点(dummyhead原指向不变);
cur = cur->next cur指向cur的下个节点;
node = dummyhead->next node指向dummyhead的下个节点.

2.链表的常见增删等操作

题号707.设计链表
设计链表的五个接口:
获取链表第index个节点的数值
在链表的最前面插入一个节点
在链表的最后面插入一个节点
在链表第index个节点前面插入一个节点
删除链表的第index个节点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注:
p=head->next p指向head的指针,只是多了p与head的关系,head原指向没影响;
head->next =p head指针指向p,即head原指向发生了改变!

在这里插入图片描述

3.反转链表

题号206.反转链表
反转一个单链表。
示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
在这里插入图片描述
首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。
然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。
为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。
接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针。
最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。
具体实现如下(双指针法
在这里插入图片描述
注:
listnode* tmp = cur->next tmp指向cur的下个节点。

4.删除链表的倒数第N个节点

题号19.删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
在这里插入图片描述
在这里插入图片描述

5.链表相交

题号02.07. 链表相交
给定两个(单向)链表,判定它们是否相交并返回交点。请注意相交的定义基于节点的引用,而不是基于节点的值。换句话说,如果一个链表的第k个节点与另一个链表的第j个节点是同一节点(引用完全相同),则这两个链表相交。
示例 1:
输入:listA = [4,1,8,4,5], listB = [5,0,1,8,4,5]
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

解析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.环形链表

题号142.环形链表II
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
在这里插入图片描述
解析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四.哈希表

1.哈希表用来快速判断一个元素是否出现集合里

哈希表是根据关键码的值而直接进行访问的数据结构。
其实直白来讲其实数组就是一张哈希表。
哈希表中关键码就是数组的索引下表,然后通过下表直接访问数组中的元素,如下图所示:
在这里插入图片描述
那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里
例如要查询一个名字是否在这所学校里。
要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1) 就可以做到。
我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。
将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数。
在这里插入图片描述

2.数组就是简单的哈希表,但是数组的大小可不是无限开辟的

题号242.有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1: 输入: s = “anagram”, t = “nagaram” 输出: true
示例 2: 输入: s = “rat”, t = “car” 输出: false
说明: 你可以假设字符串只包含小写字母。

解析:
字符串s最多只可能有26个字母,所以可以把字符串s的各字母数量保存在数组。再遍历字符串t,遇到与
s相同的字母,则对应字母的数量减1。遍历t完毕后,若数组存在非零元素,则说明t中存在着s中不存在的字母。
在这里插入图片描述
在这里插入图片描述

3.如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费

题号349. 两个数组的交集
题意:给定两个数组,编写一个函数来计算它们的交集。
在这里插入图片描述
解析:
此题不能用数组!
数值范围无限,不能用数组。不是键值对关系,不能用map,所以要用set。因为是无序,所以可以用unordered_set。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.该用set的时候,还是得用set

题号第202题. 快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 True ;不是,则返回 False 。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.两数之和

题号1.两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解析:
无限,映射关系,不要求有序,所以用undordered_map。
在这里插入图片描述
在这里插入图片描述

6.三数之和
注:三数及以上统一用双指针法

题号第15题. 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]

错解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
正解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.一样的道理,能解决四数之和 ,那么五数之和、六数之和、N数之和呢

题号第18题. 四数之和
题意:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例: 给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8.在哈希法中有一些场景就是为数组量身定做的。

题号383. 赎金信
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)
注意:
你可以假设两个字符串均只含有小写字母。
canConstruct(“a”, “b”) -> false
canConstruct(“aa”, “ab”) -> false
canConstruct(“aa”, “aab”) -> true

解析:
判断一个字符串能否由另一个字符串的字符构成。
字符数量有限,用数组即可。
在这里插入图片描述
在这里插入图片描述

五.字符串

1.反转字符串

题号344.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
输入:[“h”,“e”,“l”,“l”,“o”] 输出:[“o”,“l”,“l”,“e”,“h”] 示例 2:
输入:[“H”,“a”,“n”,“n”,“a”,“h”] 输出:[“h”,“a”,“n”,“n”,“a”,“H”]

解析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.字符串花式反转

题号541. 反转字符串II
给定一个字符串 s 和一个整数 k,你需要对从字符串开头算起的每隔 2k 个字符的前 k 个字符进行反转。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = “abcdefg”, k = 2 输出: “bacdfeg”

在这里插入图片描述
在这里插入图片描述
3.替换空格

剑指Offer 05.替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1: 输入:s = “We are happy.” 输出:“We%20are%20happy.”

解析:
首先扩充数组到每个空格替换成"%20"之后的大小。
然后从后向前替换空格,也就是双指针法,过程如下:
i指向新长度的末尾,j指向旧长度的末尾。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4.翻转字符串里的单词

题号151.翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词。
示例 1: 输入: “the sky is blue” 输出: “blue is sky the”
示例 2: 输入: " hello world! " 输出: “world! hello” 解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3: 输入: “a good example” 输出: “example good a” 解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

解析:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值