iOS算法刷题之总结梳理

201 阅读6分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

算法.png 很多开发者在面试前一段时间会找一些高频的算法题进行狂刷,这样虽然能解近渴,但可能不成体系,遇到类似的题可能解不出来。并且现在很多公司越来越看重算法能力,算法还是需要成体系进行沉淀。所以想成体系的梳理一下算法的知识。以及刚开始刷题时应该怎么刷。

一,语言选择

刷算法题首先要选择合适自己的语言,首选热门语言,如:C++、Java、Python等,因为热门语言使用的人最多,题解也会更多,在看别人题解时也会更好的理解。也有一些语言对算法支持不友好的,比如Objective-C,虽然也能写,但无法在LeetCode上提交验证,当然适合自己的语言才是最好的。

二,算法题的种类

算法题的种类很多,如:栈、队列、字符串、数组、链表、二叉树、DFS、BFS、分治算法、贪心算法、动态规划等等。算法题的难度也分为简单、中等、困难三个等级。当然一道题可能有多种解法,比如一道题可以用DFS解也可以用动态规划解,所以刷题时最好按照一定的顺序和难易程度来进行。

三,刷题顺序

1,数组、链表

首先要刷的就是基础的数据结构:数组和链表。要多刷!

数组是顺序存储,链表是链式存储,其他的数据结构如栈、队列、堆、树、图等也都是从数组和链表的数据结构演化出来的,字符串类型一般也会拆分成数组来进行处理或者也按照数组的思路处理,一定意义上来说也是数组的一种(字符串一些特有的算法不在此列)。不同的数据结构有不同的使用场景,能够解决不同的问题。

这些类型的题会比较好的培养刷题的感觉,难度一般相对也会比较低。当中用到的一些刷题技巧比如遍历、双指针、递归等也会在其他类型的题中遇到,非常适合培养算法思路和感觉。所以深入理解数组和链表后非常有助于解决其他类型的题。

数组可用到的概念包括但不限于:排序、遍历、滑动窗口、双指针(快慢指针、左右指针)、前缀和、二分搜索、区间问题、差分数组等。

链表兼具迭代和递归特性,可用到的概念包括:虚拟头节点、双指针、递归等。

对于学习算法和刷题的框架思维可以看一下labuladong的算法框架思维

2,队列、栈

数组与链表的题刷完之后可以看队列、栈相关的题,栈是先进后出;队列是先进先出,有些语言的语法支持的比较好,直接就可以使用栈和队列,但也有些语言是不支持栈和队列的,那就使用数组模拟。和数组也算是一类的题。

链表可用的概念包括但不限于,队列、栈、单调队列、单调栈等。

3,二叉树

二叉树是链表的变种,二叉树的题也要多刷,二叉树在面试中出现的频率最高,并且二叉树模型几乎是所有高级算法的基础。有了基础解决没见过的问题也会比较好解决。

二叉树可用到的概念包括但不限于:BFS、DFS、构造二叉树、序列化、二叉搜索树等。

大部分二叉树题目都可以套这个框架:

void traverse(TreeNode root) { 
    // 前序位置 
    traverse(root.left);
    // 中序位置 
    traverse(root.right);
    // 后序位置 
}

4,DFS与backtrace回溯

DFS与backtrace回溯就是一种简单粗暴的算法技巧,就是一种暴力穷举的算法。很多排列组合相关问题都可以通过DFS来解决。

DFS就是深度遍历,backtrace回溯的话是在深度遍历完后会有恢复现场的操作。DFS与backtrace回溯都会涉及到递归,也就是前面说的算法思维。

5,动态规划

暴力穷举的另外一种算法就是动态规划了,一般有关动态规划的问题,大多是让你求最值的。

动态规划的框架为:

明确basecase -> 明确【状态】 -> 明确【选择】 -> 定义dp数组/函数的含义

在定义dp数组时不要陷入到二维数组、三维数组里,而是不同的状态,然后做不同的选择。

动态规划可以分为两种方式一种是自底向上一种是自顶向下:

# 自顶向下递归的动态规划 
def dp(状态1, 状态2, ...): 
    for 选择 in 所有可能的选择: 
        # 此时的状态已经因为做了选择而改变 
        result = 求最值(result, dp(状态1, 状态2, ...)) 
    return result 
# 自底向上迭代的动态规划 
# 初始化 base case 
dp[0][0][...] = base case 
# 进行状态转移 
for 状态1 in 状态1的所有取值: 
    for 状态2 in 状态2的所有取值: 
        for ... 
            dp[状态1][状态2][...] = 求最值(选择1,选择2...)

6,分治、贪心

分治算法呢,可以认为是一种算法思想,通过将原问题分解成小规模的子问题,然后根据子问题的结果构造出原问题的答案。这里有点类似动态规划,所以说运用分治算法也需要满足一些条件,你的原问题结果应该可以通过合并子问题结果来计算。

贪心算法可以理解为一种特殊的动态规划问题,拥有一些特殊的性质,可以进一步降低动态规划的时间复杂度。

7,其他题型

算法类型种类繁多,高频的题还有数据结构类型的题、数学运算类的题等。

ps:

1,分类是按照大致进行分的,有好多题可以有多种解法。能解题才是最重要的,在能解题的基础上可以再扩展思路和尝试其他解法。

2,LeetCode算法题目前共有2827道题,算法解题思路更是博大精深。以上所列的种类可能只是九牛一毛,但写算法时可以多尝试多总结,梳理出自己的框架,最好能做到解决一道题就解决了一类题。

3,LeetCode中有很多非常好的题解,可以多看一下大佬的题解多学习一下以及扩展一下思路。

913A9E5CC42940BAA478C8D56F713E09.png

最后附上一些学习算法的资料:

labuladong的算法小抄

漫画算法:小灰的算法之旅

剑指Offer

LeetCode题解也可以看一下 宫水三叶