数据结构(一)-字符串、数组与链表

先回顾时间复杂度和空间复杂度,并深入最简单的数据结构-数据和链表的内存结构
https://www.runoob.com/w3cnote/ten-sorting-algorithm.html

算法:5遍刷题法,空间换时间

字符串

很多时候,在分析字符串相关面试题的过程中,我们往往要针对字符串当中的每一个字符进行分析和处理,甚至有时候我们得先把给定的字符串转换成字符数组之后再进行分析和处理。

举例

翻转字符串“algorithm”。

因csdn不能上传gif动态图,所以这里没有展示图。

解法:用两个指针,一个指向字符串的第一个字符 a,一个指向它的最后一个字符 m,然后互相交换。交换之后,两个指针向中央一步步地靠拢并相互交换字符,直到两个指针相遇。这是一种比较快速和直观的方法。

注意:由于无法直接修改字符串里的字符,所以必须先把字符串变换为数组,然后再运用这个算法。

数组

数组是内存中一段联系的空间。可以参考ArrayList源码。以及双向链表实现LinkedList。

数组的优缺点

要掌握一种数据结构,就必须要懂得分析它的优点和缺点。数组的优点在于:

  1. 构建非常简单
  2. 能在 O(1) 的时间里根据数组的下标(index)查询某个元素

而数组的缺点在于:

  1. 构建时必须分配一段连续的空间
  2. 查询某个元素是否存在时需要遍历整个数组,耗费 O(n) 的时间(其中,n 是元素的个数)
  3. 删除和添加某个元素时,同样需要耗费 O(n) 的时间

举例

LeetCode 第 242 题:给定两个字符串 s 和 t,编写一个函数来判断 t 是否是 s 的字母异位词。
说明:你可以假设字符串只包含小写字母。字母异位词,也就是两个字符串中的相同字符的数量要对应相等。
示例 1
输入: s = “anagram”, t = “nagaram”。
输出: true。因为它们都包含有三个字符 a,一个字符 g,一个字符 m,一个字符 n,以及一个字符 r。
示例 2
输入: s = “rat”, t = “car”
输出: false。而当 s 为 “rat”,t 为 “car”的时候,s 和 t 不互为字母异位词。

解题思路

一个重要的前提“假设两个字符串只包含小写字母”,小写字母一共也就 26 个,因此:
可以利用两个长度都为 26 的字符数组来统计每个字符串中小写字母出现的次数,然后再对比是否相等;

可以只利用一个长度为 26 的字符数组,将出现在字符串 s 里的字符个数加 1,而出现在字符串 t 里的字符个数减 1,最后判断每个小写字母的个数是否都为 0。

按上述操作,可得出结论:s 和 t 互为字母异位词。

链表

链表是一种数据结构,和数组同级。比如,Java 中我们使用的ArrayList,其实现原理是数组。而LinkedList 的实现原理就是链表了。链表在进行循环遍历时效率不高,但是插入和删除时优势明显。
在这里插入图片描述
链表分为:
单链表:链表中的每个元素实际上是一个单独的对象,而所有对象都通过每个元素中的引用字段链接在一起。
双链表:与单链表不同的是,双链表的每个结点中都含有两个引用字段。

链表的优缺点

  1. 链表的优点如下:
    链表能灵活地分配内存空间;
    能在 O(1) 时间内删除或者添加元素,前提是该元素的前一个元素已知,当然也取决于是单链表还是双链表,在双链表中,如果已知该元素的后一个元素,同样可以在 O(1) 时间内删除或者添加该元素。

  2. 链表的缺点是:
    不像数组能通过下标迅速读取元素,每次都要从链表头开始一个一个读取;
    查询第 k 个元素需要 O(k) 时间。
    应用场景:如果要解决的问题里面需要很多快速查询,链表可能并不适合;如果遇到的问题中,数据的元素个数不确定,而且需要经常进行数据的添加和删除,那么链表会比较合适。而如果数据元素大小确定,删除插入的操作并不多,那么数组可能更适合。

经典解法

  1. 利用快慢指针(有时候需要用到三个指针)

典型题目例如:链表的翻转,寻找倒数第 k 个元素,寻找链表中间位置的元素,判断链表是否有环等等。

  1. 构建一个虚假的链表头

一般用在要返回新的链表的题目中,比如,给定两个排好序的链表,要求将它们整合在一起并排好序。又比如,将一个链表中的奇数和偶数按照原定的顺序分开后重新组合成一个新的链表,链表的头一半是奇数,后一半是偶数。

在这类问题里,如果不用一个虚假的链表头,那么在创建新链表的第一个元素时,我们都得要判断一下链表的头指针是否为空,也就是要多写一条 if else 语句。比较简洁的写法是创建一个空的链表头,直接往其后面添加元素即可,最后返回这个空的链表头的下一个节点即可。

建议:在解决链表的题目时,可以在纸上或者白板上画出节点之间的相互关系,然后画出修改的方法,既可以帮助你分析问题,又可以在面试的时候,帮助面试官清楚地看到你的思路。

举例

LeetCode 第 25 题:给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定这个链表:1->2->3->4->5
当 k=2 时,应当返回:2->1->4->3->5
当 k=3 时,应当返回:3->2->1->4->5

解题思路

这道题考察了两个知识点:

  1. 对链表翻转算法是否熟悉
  2. 对递归算法的理解是否清晰

在翻转链表的时候,可以借助三个指针:prev、curr、next,分别代表前一个节点、当前节点和下一个节点,实现过程如下所示。
在这里插入图片描述

  1. 将 curr 指向的下一节点保存到 next 指针;
  2. curr 指向 prev,一起前进一步;
  3. 重复之前步骤,直到 k 个元素翻转完毕;
  4. 当完成了局部的翻转后,prev 就是最终的新的链表头,curr 指向了下一个要被处理的局部,而原来的头指针 head 成为了链表的尾巴。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值