【LeetCode解题总结】数组/字符串篇

基本数据结构

数组/字符串

优点

  • 构建非常简单
  • 能在 O(1) 的时间里根据数组的下标(index)查询某个元素
  • 小写字母一共就 26 个

缺点

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

性质

  • 长度为n的字符串,共有n×(n + 1) / 2 + 1 个子串,2n个子序列

应用场景

考虑是否应当采用数组去辅助你的算法时,请务必考虑它的优缺点,看看它的缺点是否会阻碍你的算法复杂度以及空间复杂度

常见解题思路

数组

注意事项

  • 总结规律时注意边界条件(例如,比较两个元素的大小时,要注意只有1个元素输入的情况)

具体方法

  1. 滑动窗口法

    LeetCode 滑动窗口(Sliding Window)类问题总结

    题目 思路
    3. 无重复字符的最长子串
    340. 至多包含 K 个不同字符的最长子串
  2. 指针法

    每定义一个指针都要注意它指向的具体位置,是否可能越界

字符串

注意事项

  • 注意区分String,char和StringBuilder

具体方法

  1. 高精度计算

  2. 字符串变换

    6. Z 字形变换 :找出字符串前后每个字符的映射关系

高级数据结构

前缀树

性质

  • 每个节点至少包含两个基本属性
    • children:数组或者集合,罗列出每个分支当中包含的所有字符
    • isEnd:布尔值,表示该节点是否为某字符串的结尾
  • 前缀树的根节点是空的
    • 所谓空,即只利用到这个节点的 children 属性,即只关心在这个字典里,有哪些打头的字符
  • 除了根节点,其他所有节点都有可能是单词的结尾,叶子节点一定都是单词的结尾

基本操作

创建
  • 遍历一遍输入的字符串,对每个字符串的字符进行遍历
  • 从前缀树的根节点开始,将每个字符加入到节点的 children 字符集当中
  • 如果字符集已经包含了这个字符,则跳过
  • 如果当前字符是字符串的最后一个,则把当前节点的 isEnd 标记为真
搜索
  • 与创建方法类似,从前缀树的根节点出发,逐个匹配输入的前缀字符,如果遇到了就继续往下一层搜索,如果没遇到,就立即返回。

总结

常用于打字法/搜索引擎的联想输出

出现在许多面试的难题当中。
因为很多时候你得自己实现一棵前缀树,所以你要能熟练地书写它的实现以及运用它。

例题

208. 实现 Trie (前缀树)

336. 回文对

线段树

性质

  • 线段树,就是一种按照二叉树的形式存储数据的结构,每个节点保存的都是数组里某一段的总和。
  • 适用于数据很多,而且需要频繁更新并求和的操作。
  • 时间复杂度 O(logn)。

基本操作

更新数组里某个元素的数值

从线段树的根节点出发,更新节点的数值,它保存的是数组元素的总和。修改的元素有可能会落在线段树里一些区间里,至少叶子节点是肯定需要更新的,所以,要做的是从根节点往下,判断元素的下标是否在左边还是右边,然后更新分支里的节点大小。因此,复杂度就是遍历树的高度,即 O(logn)。

对数组某个区间段里的元素进行求和

方法和更新操作类似,首先从根节点出发,判断所求的区间是否落在节点所代表的区间中。如果所要求的区间完全包含了节点所代表的区间,那么就得加上该节点的数值,意味着该节点所记录的区间总和只是所要求解总和的一部分。接下来,不断地往下寻找其他的子区间,最终得出所要求的总和。

例题

树状数组

性质

  • 求解前 k 个元素的总和,并不要求任意一个区间
  • 可以在 O(logn) 的时间里完成上述的操作
  • 相对于线段树的实现,树状数组显得更简单

实现

  • 它是利用数组来表示多叉树的结构,在这一点上和优先队列有些类似,只不过,优先队列是用数组来表示完全二叉树,而树状数组是多叉树。
  • 树状数组的第一个元素是空节点。
  • 如果节点 tree[y] 是 tree[x] 的父节点,那么需要满足条件:y = x - (x & (-x))。

总结

应用场合比较明确。求区间统计值时可以使用

例题

原文地址:https://www.cnblogs.com/JasonBUPT/p/11867222.html