算法之"朝花夕拾"

95 阅读10分钟

算法模式分类总结

最近工作之余,开始想要温习各类算法,给自己定个计划,对算法来个“朝花夕拾”。在知乎看到一个非常好的刷题类型总结,这里也做一个记录总结分类。


1. Pattern: Sliding window(滑动窗口类型)

滑动窗口类型的算法题经常是用来执行数组或者链表上某个区间(窗口)上的操作。

经典算法题如下:

  • Max Sum Subarray of Size K
  • Smallest Subarray with a given sum
  • Longest SubString with K Distinct Characters
  • Fruits into Baskets
  • No-repeat Substring
  • Longest Substring with Same Letters after Replacement
  • Longest Subarray with Ones after Replacement

2. Pattern: Two Pointers(双指针类型)

双指针模式:两个指针朝着左右方向移动(同向双指针、异向双指针),直到指针有一个或两个同时满足某种条件。

经典算法题如下:

  • Pair with Target Sum
  • Remove Duplicates
  • Squaring a Sorted Array
  • Triplet Sum to Zero
  • Triplet Sum Close to Target
  • Triplets with Smaller Sum
  • Subarrays with Product Less than a Target
  • Dutch National Flag Problem

3. Pattern: Fast & Slow pointers(快慢指针类型)

龟兔赛跑,这种算法的两个指针在数组上(或是链表上、序列上)的移动速度不一样。这种方法在解决有环的链表和数组时特别有用,快的指针肯定会追上慢的指针。

适用于以下场景:

  • 问题需要处理环上的问题,比如环形链表和环形数组;
  • 当你需要知道链表的长度或是某个特别位置信息的时候;
  • 单链表无法往回移动,建议用双指针。

经典算法题如下:

  • LinkedList Cycle
  • Start of LinkedList Cycle
  • Happy Number
  • Middle of the LinkedList

4. Pattern: Merge Intervals(区间合并类型)

用来处理有区间重叠的问题很高效。

经典算法题如下:

  • Merge Interval
  • Insert Interval
  • Intervals Intersection
  • Conflicting Appointments

5. Pattern: Cyclic Sort(循环排序)

用来处理数组中的数值限定在一定区间的问题。一般设计在排序好的数组,而且数值一般满足于一定的区间。比如要你在排序好的数组中,寻找丢失/重复/最小的元素。

经典算法题如下:

  • Cyclic Sort
  • Find the Missing Number
  • Find all Missing Numbers
  • Find the Duplicate Number
  • Find all Duplicate Numvers

6. Pattern: In-place Reversal of a LinkedList (链表翻转)

一般题目要求你翻转某一段的节点,有时候要求你全部翻转。用来处理原地翻转,而不需要使用额外的空间。

经典算法题如下:

  • Reverse a LinkedList
  • Reverse a Sub-list
  • Reverse every K-element Sub-list

7. Pattern: Tree Breadth First Search (树上的BFS)

一般题目用于宽搜,适用于需要遍历一棵树。可能需要用到每一层的节点做运算,可借助于队列数据结构,保证将树的节点按照层数打印出来。其模式通过把根节点加到队列中,然后不断的遍历直到队列为空。每次循环中,将队头节点remove掉,再对其做相关操作。在删除每个节点的同时,其孩子节点会被加入到队列中。【层序遍历】

经典算法题如下:

  • Binary Tree Level Order Travelsal
  • Reverse Level Order Traversal
  • Zigzag Traversal
  • Level Averages in a Binary Tree
  • Minimum Depth of a Binary Tree
  • Level Order Successor
  • Connect Level Order Siblings

8. Pattern: Tree Depth First Search (树上的DFS)

树形DFS基于深搜来实现树的遍历。可用递归、栈的方式来记录遍历过程中访问过的父节点,该模式的运行方式是从根节点开始,如果该节点不是叶子节点:
①需要区别是使用前序、中序、后序来处理根节点。
②递归处理当前节点的左右孩子。

该问题的解一般离叶子节点比较近。

经典算法题如下:

  • Binary Tree Path Sum
  • All Paths for a Sum
  • Sum of Path Numbers
  • Path With Given Squence
  • Count Paths for a Sum

9. Pattern: Two Heaps (双堆类型)

一般题目给你一大堆可以分成两队的数据,例如让你把小的数字都放在一起,大的放在另外一队。最小堆用来找最小元素;最大堆拿到最大元素。该模式下将一半的元素放在最大堆中,这样你可以在该堆中迅速找到最大元素;再将剩下的一半丢到最小堆中,又能迅速找到最小元素,且查询最大、最小的复杂度都在O(1)。通过这样的方式,这一堆元素的中位数就可以从两个堆的堆顶拿到数字,就方便计算了。

1、计划安排问题中有奇效。
2、从一组数中寻找最大/最小/中位
3、在二叉树结构里也很有用。

经典算法题如下:

  • Find the Median of a Number Stream
  • Sliding Window Median
  • Maximize Capital

10. Pattern: Subsets (子集类型)

一般用于多重DFS,很多题目会涉及到排列和组合的问题。子集问题是用BFS来处理这些问题。

给出一组数字集合[1,5.3]

1、首先是初始化空集:[[]];
2、把第一个数1,加到之前已经存在的集合中[[],[1]];
3、把第二个数5,加到之前的集合中得到[[],[1],[5],[1,5]];
4、最后加上第三个数3,则为[[],[1],[5],[1,5],[3],[1,3],[5,3],[1,5,3]].

经典算法题如下:

  • Subsets
  • Subsets With Duplicates
  • Permutations
  • String Permutations by changing case
  • Balanced Parentheses
  • Unique Generalized Abbreviations

11. Pattern: Modified Binary Search (改造过的二分搜索)

当你需要解决的问题输入是排序好的数组、链表或者是排序好的矩阵,要求寻找某些特定元素。这个时候最好的选择就是二分搜索。
对于一组满足上升排序的数集来说,以下步骤是这样的:
1、首先算出左右端口的中点。最简单的方式是:middle= (start + end)/2。但这种计算方式有概率会出现整数越界。因此一般使用这种写法:middle=start + (end - start)/2
2、如果要找的目标刚好和中点所在的数值相等,我们返回中点的下标即可。 3、如果目标不相等:我们有两种移动方式:

  • 如果目标比中点值小,将下一步搜索空间放在中点位置的左边(end=middle - 1)

  • 如果目标比中点值大,将下一步搜索空间放在中点位置的右边(start=middle + 1)

经典算法题如下:

  • Order-agnostic Binary Search
  • Ceiling of a Number
  • Next Letter
  • Number Range
  • Search in a Sorted Infinite Array
  • Minimum Difference Element
  • Bitonic Array Maximum

12. Pattern: Top 'K' Elements (前K个系列)

任何让求解最大、最小、最频繁的K个元素的题,都遵循该模式。

用来记录这种前K类型的最佳数据结构就是堆。这种模式借助堆来解决很多这种前K个数值的问题。该模式如下:

  • 根据题目要求,将K个元素插入到最大堆或最小堆。

  • 遍历剩下还没有访问的元素,如果当前元素比堆顶元素大,就先把堆顶元素删除,再加当前元素进去。
    该模式下无需对数组做排序,堆具有良好的局部有序性,对于解决问题已足够。

经典算法题如下:

  • Top 'K' Numbers
  • Kth Smallest Number
  • 'K' Closest Points to the Origin
  • Connect Ropes
  • Top 'K' Frequent Numbers
  • Frequency Sort
  • Kth Largest Number in a Stream
  • 'K' Closest Numbers
  • Maximum Distinct Elements
  • Sum of Elements
  • Rearrange String

13. Pattern: K-way merge (多路归并)

K路归并能解决涉及多组已经排序好的数组问题。

每当输入为K个排好序的数组,你就可以用堆来高效顺序遍历其中所有数组的元素。可以将每个数组中的最小元素加入到最小堆,从而得到全局最小值。当拿到全局最小值后,再从该元素所在数组里取出其后紧挨着的元素加入堆,如此往复直到处理完所有元素。
该模式是这样运行的:

  • 把每个数组中的第一个元素加入最小堆。
  • 取出堆顶元素,将该元素放入排好序的结果结合中。
  • 将刚取出的元素所在的数组里面的下一个元素加入堆。
  • 重复上述两个步骤,直到处理完所有数字。

识别K路归并:

  • 该问题的输入是排好序的数组、链表或矩阵。

  • 如果需要合并多个排好序的结合,或是找到这些集合中最小的元素。

经典算法题如下:

  • Merge K Sorted Lists
  • Kth Smallest Number in M Sorted Lists
  • Kth Smallest Number in a Sorted Matrix
  • Smallest Number Range

14. Pattern: 0/1 Knapsack (动态规划-0/1背包问题)

经典算法题如下:

  • 0/1 Knapsack
  • Equal Subset Sum Partition
  • Subset Sum
  • Minimum Subset Sum Difference

15. Pattern: Topological Sort(Graph) (拓扑排序)

拓扑排序用来寻找一种线性的排序,这些元素之间具有依赖性。例如,事件B依赖于事件A,那A在拓扑排序中排在B前面。
该模式是这样奏效的:

  • 初始化
    ①借助于HashMap将图保存成邻接表形式。
    ②找到所有的起点,用HashMap来帮助记录每个节点的入度。
  • 创建图,找到每个节点的入度。
    ①利用输入把图建好,然后遍历一下图,将入度信息记录在HashMap中。
  • 找所有的起点
    ①所有入度为0的节点,都是有效的起点,都将其加入到一个队列中。
  • 排序
    ①对每个起点,执行以下步骤:
    (1) 把它加到结果的数组中
    (2) 将其在图中的孩子节点取到。
    (3) 将其孩子节点的入度减1
    (4) 如果孩子节点的入度为0,则将孩子节点改为起点,将其加入队列中。
    ②重复①中步骤,直到起点队列为空

拓扑排序模式识别

  • 待解决的问题需要处理无环图

  • 需要以一种有序的秩序更新输入元素

  • 需要处理的输入遵循某种特定的顺序

经典算法题如下:

  • Topological Sort
  • Tasks Scheduling
  • Tasks Scheduling Order
  • All Tasks Scheduling Orders
  • Alien Dictionary

16. Pattern: Topological Sort(Graph) (拓扑排序)

拓扑排序用来寻找一种线性的排序,这些元素之间具有依赖性。例如,事件B依赖于事件A,那A在拓扑排序中排在B前面。
该模式是这样奏效的:

  • 初始化
    ①借助于HashMap将图保存成邻接表形式。
    ②找到所有的起点,用HashMap来帮助记录每个节点的入度。
  • 创建图,找到每个节点的入度。
    ①利用输入把图建好,然后遍历一下图,将入度信息记录在HashMap中。
  • 找所有的起点
    ①所有入度为0的节点,都是有效的起点,都将其加入到一个队列中。
  • 排序
    ①对每个起点,执行以下步骤:
    (1) 把它加到结果的数组中
    (2) 将其在图中的孩子节点取到。
    (3) 将其孩子节点的入度减1
    (4) 如果孩子节点的入度为0,则将孩子节点改为起点,将其加入队列中。
    ②重复①中步骤,直到起点队列为空

拓扑排序模式识别

  • 待解决的问题需要处理无环图

  • 需要以一种有序的秩序更新输入元素

  • 需要处理的输入遵循某种特定的顺序

经典算法题如下:

  • Topological Sort
  • Tasks Scheduling
  • Tasks Scheduling Order
  • All Tasks Scheduling Orders
  • Alien Dictionary

文章内容总结来自:www.zhihu.com/question/36…
仅做个人总结使用,如需商用请咨询作者本人