GithubHelp home page GithubHelp logo

shannonchenchn / algorithm-and-data-structure Goto Github PK

View Code? Open in Web Editor NEW
2.0 2.0 1.0 5.72 MB

Algorithms + Data Structures = Programs

Swift 55.61% Objective-C 16.02% C 3.65% C++ 24.72%
datastructuresandalgorithm

algorithm-and-data-structure's People

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

dehzao

algorithm-and-data-structure's Issues

LeetCode 应该怎么刷

算法练习: 优先队列和堆(Priority Queue & Heap)

优先队列

A priority queue is a queue where the most important element is always at the front.

The queue can be a max-priority queue (largest element first) or a min-priority queue (smallest element first).

参考:

题目列表

总结

  1. 需要掌握的基础知识有:
    • 什么是堆
      • 完全二叉树
      • 父比子大/小
    • 如何实现一个堆
      • 存储:一般是数组
      • 操作:insert、remove、shiftUp、shiftDown
    • 堆排序:建堆+排序
  2. 遇到求 Top K 或者第 K 大的数这类问题时,都可以考虑是否用堆来实现
  3. 重点掌握建堆的模板代码

算法练习:哈希表/散列表(Hash Table)

题目列表

总结

  • 哈希表的实现
  • 散列函数
  • 如何解决散列冲突
    • 开放寻址法
    • 链表法

算法练习: 栈(Stack)

题目列表

基于数组实现一个栈

struct Stack<Element> {
    
    private var storage: [Element] = []
    
    mutating func push(_ object: Element) {
        storage.append(object)
    }
    
    @discardableResult
    mutating func pop() -> Element? {
        storage.popLast()
    }
    
    func peek() -> Element? {
        return storage.last
    }
    
    func isEmpty() -> Bool {
        return storage.isEmpty
    }
}

extension Stack: CustomStringConvertible {
    var description: String {
        return storage.description
    }
}

extension Stack: ExpressibleByArrayLiteral {
    init(arrayLiteral elements: Element...) {
        self.init()
        for element in elements {
            self.push(element)
        }
    }
}

总结

  1. 关于栈的题型主要有以下几类:
    1). 首先是跟栈数据结构本身相关的,可以直接从标题或者描述中看出来是要考察栈的,比如 剑指 Offer 31. 栈的压入、弹出序列155. Min Stack
    2). 另外一类是跟栈的几个典型应用场景相关的:

3). 还有一类题型是因为正好可以利用栈“后进先出”的特性来解决问题的(但并不一定是最优解),比如回删操作、后退操作这类问题,相关题目有 844. Backspace String Compare19. 删除链表倒数第 n 个结点682. Baseball Game

  1. Swift 中没有 Stack 类,但是可以用数组模拟栈的操作。popLast() 相当于 pop 操作,append() 相当于 push 操作

算法练习:排序

题目列表

实现几种常见的排序算法,并计算相应的时间复杂度和空间复杂度

LeetCode

其他

总结

  1. 关键要掌握以下几点:
  • 几种常见的排序算法的原理和适应场景
  • 时间复杂度和空间复杂度分析
  • 重点掌握前五种排序算法的实现,尤其是快排的实现,一定要熟记,很多题目的解法都是基于 partition 函数的实现
  1. 跟排序相关的常考题型主要有 Top K 问题、求第 K 大元素。
  2. 各排序算法的比较
    image

算法练习: 数组和字符串

题库来源:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/x6w3ds/

一、题目列表

数组

字符串

二、相关专题

总结

  • Swift 中 Character 的常用 API
    • asciiValue
    • isNumber
    • isLetter
    • isWhitespace
    • isNewline
    • wholeNumberValue
    • lowercased()
    • uppercased()
  • 为了方便逐个访问 String 中的字符,我们可以将一个 String 类型的变量转成 Array,比如 let str = "abc" 可以转成 let charArray = Array(str)
  • 字符串处理的题目往往涉及复杂的流程以及条件情况,如果直接上手写程序,一不小心就会写出极其臃肿的代码。
  • 一旦涉及整数的运算,我们需要注意溢出。对于溢出的处理方式通常可以转换为 Int.max 的逆操作,比如判断某数乘 10 是否会溢出,那么就把该数和 Int.max 除 10 进行比较:num > Int.max / 10 || (num == Int.max / 10 && curChar.wholeNumberValue > Int.max % 10)
  • 字符串的题目一般会经常用双指针法来求解

算法练习:常用算法设计**之四——动态规划(Dynamic Programming)

题目列表

总结

  • 看到题目后,首先要分析能不能用动态规划解,一般先试试用暴力穷举法能不能做出来,然后再看是否符合”一个模型三个特征“
  • 绝大多数动态规划的问题都是一维和二维的,只有极少数会涉及到三维(比如123. 买卖股票的最佳时机 III)
  • 动态规划解题五步曲
    • 状态定义:这个往往跟题目中要求的最优解有关,一般是直接相关,也有个别情况并不是直接相关,比如 300. 最长递增子序列
    • 状态转移方程:写状态转移方程时需要考虑到遍历的维度,也就是状态是怎么转移的,一般都是比较简单的 i j 递增,但是有些特殊情况也要具体分析,比如 5. 最长回文子串 这一题
    • 状态初始化:写完状态转移方程之后,还需要考虑到一些边界条件,也就是状态初始化
    • 返回结果
    • 空间优化:AC 之后,再看看是否有空间优化的可能,一般情况下二维数组可以优化成一维数组(画矩阵表),一维数组可以优化成两个非集合类型的变量
  • 写完之后,一定要自己跑几个 case 验证一下,注意各种边界条件
  • 字符串比较求最优解这类问题一般都可以用动态规划求解,值得注意的是,一般定义状态时会把dp[i][j]表示前 i, j 个字符串的状态,但是在遍历字符串时一定要记得前 i 个字符串的最后一个字符是第 i-1 位而不是第 i 位。比如 10. 正则表达式匹配

【算法练习】数组:二维数组中的查找

在一个二维数组中,每一行都按照从左到右递增的顺序排列,每一列都按照从上到下递增的顺序排列。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

例如,从下面的数组中查找 7 返回 true,查找 5 返回 false。

1    2    8    9
2   4    9    12
4   7    10   13
6   8    11   15

理解算法的时间复杂度和空间复杂度

目录

  • 一、什么是算法复杂度
  • 二、为什么要分析算法复杂度
  • 三、如何分析算法复杂度
    • 大 O 表示法:T(n)=O(f(n))
      • 公式中的低阶、常量和系数可以忽略
    • 时间复杂度
      • 分析技巧
        • 单段代码看最高频:如果一个函数中有多个循环,只关注循环执行次数最多的一段代码
        • 加法法则:总复杂度等于量级最大的那段代码的复杂度
        • 乘法法则:嵌套代码求乘积,比如递归、多重循环
        • 多个规模求加法:比如方法有两个不同的参数控制两个循环的次数
      • 几种常见时间复杂度实例分析
        • 多项式量级:O(1)、O(logn)、O(n)、O(nlogn)、O(n^2)、O(n^3)...
        • 非多项式量级:O(2^n)、O(n!)
      • 几种不同情况的复杂度
        • 最好情况时间复杂度
        • 最坏情况时间复杂度
        • 平均情况时间复杂度
        • 均摊时间复杂度
    • 空间复杂度
  • 四、如何掌握复杂度分析
    • 多练,熟能生巧

算法练习:滑动窗口(Sliding Window)

题目列表

总结

  • 什么是滑动窗口算法
  • 需要记住滑动窗口算法的基本步骤
  • 滑动窗口算法适合用来解决哪一类问题?

算法练习:查找

题目列表

总结

  • 需要熟练掌握二分查找法的实现过程,以及复杂度分析
  • 只要遇到排序数组或者部分排序数组的场景,都要条件反射地想到二分查找是不是可以派上用场,二分查找的核心在于排除法
  • 二分模板虽然多,但是具体题目要具体分析,多做题比模板更重要,做多了就灵活了,你不可能靠模板就能解决所有算法问题(网友评论)
  • 如果题目给出的是有序的数组,除了可以使用二分查找,还有一个更高效的方法就是双指针。

算法练习:回文构词法(Anagram)

题目 1 判断 Anagram

描述

Given two strings s and t, write a function to determine if t is an anagram of s.
For example,
s = "anagram", t = "nagaram", return true. s = "rat", t = "car", return false.

Note:

You may assume the string contains only lowercase alphabets.

分析

方案1:为s和t分别建立一个HashMap,统计每个字母出现的次数,比较两个HashMap是否相等。时间复杂度O(n),空间复杂度O(n),n为字符串长度。

方案2:题目中的字符串只包含小写的字母,意味着只有从a-z的26个字母,于是我们可以为s和t开一个长度为26的整数数组来代替哈希表,此时额外空间为固定长度的两个数组,因此为O(1)。

#define ALPHABET_SIZE  26

BOOL isAnagram(NSString *s, NSString *t) {
    if (s.length != t.length) {
        return NO;
    }
    
    int map[ALPHABET_SIZE] = {}; // C 数组必须要初始化,才能保证所有元素初始值为 0
    for (int i = 0; i < s.length; i++) {
        int indexForS = [s characterAtIndex:i] - 'a';
        map[indexForS] = map[indexForS] + 1;
        
        int indexForT = [t characterAtIndex:i] - 'a';
        map[indexForT] = map[indexForT] - 1;
    }
    
    for (int i = 0; i < ALPHABET_SIZE; i++) {
        if (map[i] != 0) {
            return NO;
        }
    }
    
    return YES;
}

参考

《算法面试通关40讲》学习笔记

课程地址:https://time.geekbang.org/course/detail/100019701-41518
ppt 地址:https://github.com/ShannonChenCHN/algorithm-1

课程介绍

  • 大厂面试一般都会重点考察算法和数据结构
  • 解决算法和数据结构相关问题的能力可以通过学习和训练不断提高的
  • LeetCode 上题目越来越多,求职者不可能在短时间内把题目全部做完,如何有选择性地来练习和准备算法面试,就成为大多数求职者必须面对的难题
  • 这个课程的目标是,帮助求职者在短时间内掌握面试中最常见的算法与数据结构相关知识点,学会面试中高频算法题目的分析思路,同时给大家从面试官的角度来分析算法题的解答技巧,从而更有效地提升求职者的面试通过率

课程结构

  • 课程综述(4讲)
  • 理论讲解加+面试题实战(53讲)
  • 课程总结(5讲)

e61550fe597b2b351c72e333b57bb0d6

e61550fe597b2b351c72e333b57bb0d6的副本

算法练习:树(Tree)

题目列表

1. 二叉树

  1. 二叉搜索树

  1. #25

  2. 平衡二叉树

  1. 其他

总结

  1. 关于树的一些基本概念一定要掌握,比如高度、深度、层数、叶子节点。
  2. 需要知道什么是二叉搜索树、平衡二叉树、完全二叉树和满二叉树,像红黑树这类了解即可。
  3. 完全二叉树的由来(如何表示/存储一棵二叉树?)
  4. 根据二叉搜索树的典型特征,中序遍历可以得到一个递增序列。一般来讲,只要遇到二叉搜索树的题目,马上就要能想到两点:
    - 中序遍历得到的序列是单调递增的
    - 所有的左子树上的节点值都小于根节点,所有的右子树上的节点值都大于根节点
  5. 需要熟练掌握二叉树的前序、中序、后序遍历的递归实现(迭代实现了解即可),以及层序遍历的实现,这两类遍历对应的也就是常说的 DFS 和 BFS,绝大部分二叉树的题目都是考察这两点的。另外还需要熟练掌握这类算法的复杂度分析。
  6. 只要是二叉树的题目,第一反应就是递归怎么实现?递推公式怎么写?
  7. 上面题目列表中标记 ⭐️ 的题目都是典型的二叉树的题目,需要多做几遍,达到非常熟练的程度。

LeetCode 经典面试题集-初级算法

概述

这是由 LeetCode 官方推出的的经典面试题目清单,我们将题目重新整理规划,从而为大家提供更好的练习体验和帮助大家找到理想的工作。 我们将题目分为以下三个部分:

这一系列 LeetBook 将帮助您掌握算法及数据结构,并提高您的编程能力。

编程能力就像任何其他技能一样,也是一个可以通过 刻意练习 大大提高的。

大多数经典面试题目都有多种解决方案。 为了达到最佳的练习效果,我们强烈建议您至少将此清单里的题目练习两遍,如果可以的话,三遍会更好

在第二遍练习时,你可能会发现一些新的技巧或新的方法。 到第三遍的时候,你会发现你的代码要比第一次提交时更加简洁。 如果你达到了这样的效果,那么恭喜你,你已经掌握了正确的练习方法!

记住:刻意练习并不意味着寻找答案并记住它,这种练习方法不是长久之计。 在没有参考答案情况下,越能自主解决问题,才越能提高自身能力。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/x6w3ds/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

【算法练习】数组:找出重复的数字

题目一:

从一个长度为 n,且所有元素大小都在 0~n-1 范围内的数组中,找出任意重复的数字。比如,输入一个长度为 7 的数组 {2, 3, 1, 0, 2, 5, 3},那么结果应该是重复数字 2 或者 3。

解法

👉戳这里

算法练习:字典树/前缀树 (Trie)

题目列表

总结:

  1. 需要掌握 Trie 的实现
    • 需要注意的是 Trie 和多叉树的区别,建议画图结合图来看。
    • 记住 208 题 的模板代码
      • 节点结构
      • 插入单词
      • 查找单词
      • 前缀匹配
  2. 简单概括 Trie 的应用就是:一次建树,多次查询
    • 搜索引擎关键词输入的自动联想
    • 拼写检查
    • IP 路由地址前缀匹配
  3. Trie 的性质
    • Trie 的形状和单词的插入或删除顺序无关,也就是说对于任意给定的一组单词,Trie 的形状都是唯一的。
    • 查找或插入一个长度为 L 的单词,访问 next 数组的次数最多为 L+1,和 Trie 中包含多少个单词无关。
    • Trie 的每个结点中都保留着一个字母表,这是很耗费空间的。如果 Trie 的高度为 n,字母表的大小为 m,最坏的情况是 Trie 中还不存在前缀相同的单词,那空间复杂度就为 O(m^n)。

算法练习: 队列和双端队列(Queue & Deque)

理论知识

  1. 队列
  1. 双端队列

题目列表

总结

  1. 队列和栈有两个最大的不同点: 1) 栈是“先进后出”、队列是“先进先出”;2)队列是两端可以操作,而栈只有一端可以操作。这两点在题目 225. Implement Stack using Queues232. Implement Queue using Stacks 中就体现出来了。
  2. 队列既可以用数组来实现,又可以用链表来实现。具体的实现过程见题目 分别用数组和链表实现一个队列实现一个循环队列
  3. Swift 的标准库中没有提供 Stack 和 Queue,不过我们可以用 Array 来模拟 Stack 和 Queue 的操作。
  4. 均摊复杂度分析:通过题目 232. Implement Queue using Stacks 的练习,正好顺便复习了一下均摊时间复杂度的分析以及什么时候需要用到 均摊时间复杂度。

算法练习: 链表(Linked List)

题目列表

必做题

其他

进阶题

总结

  • 链表问题相对容易掌握,但需要多阅读优秀简洁的代码和反复练习才能减少出错的概率,尤其是要反复练习
  • 一个比较容易出错的地方是,我们插入、删除或者交换结点时,一定要注意操作的顺序,避免出现指针丢失的问题
  • 在写代码时,需要重点留意边界条件处理
    • 如果链表为空时,代码是否能正常工作?
    • 如果链表只包含一个结点时,代码是否能正常工作?
    • 如果链表只包含两个结点时,代码是否能正常工作?
    • 代码逻辑在处理头结点和尾结点的时候,是否能正常工作?
    • 其他边界情况
  • 在思考思路和写代码时可以多借助画图和举例的办法帮助思考
  • "双指针解法" 是一个很好用的方法,它不仅适用于数组问题,而且还适用于链表问题。比如,141. 链表中环的检测19. 删除链表倒数第 n 个结点
  • 另一种大大简化链接列表问题的方法是 "Dummy node" 节点技巧(又称哨兵节点) ,所谓 Dummy Node 其实就是指向头节点的指针。针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个结点的情况进行特殊处理,这个时候借助 Dummy Node 可以让代码实现变得更简单。
  • 有时候递归也可以解决链表问题,递归有点不太好理解,需要记住的两点是:递归可以实现单链表的逆序遍历;递归需要考虑函数压栈占用的空间复杂度
  • 在解决某些限制条件比较严格的问题时,比如第 234 题和第 237 题,我们可以通过修改原始链接的部分结构来实现
  • 相关题型总结:https://leetcode-cn.com/problems/middle-of-the-linked-list/solution/kuai-man-zhi-zhen-zhu-yao-zai-yu-diao-shi-by-liwei/

算法练习:位运算和数学问题(Bit Manipulation & Math)

题目列表

位运算

数学问题

总结

  1. 把一些常用的位运算特点背下来
    • &,或 |,非 ~,异或 ^,左移 <<,右移 >>
    • (x & 1) == 1 等价于 (x % 2 == 1)
    • (x & 1) == 0 等价于 (x % 2 == 0)
    • x / 2 等价于 x >> 1
    • x &= (x - 1) 把x最低位的二进制1给去掉
    • x & -x 只保留最低位的1,而把其他位的1都去掉
    • x & ~x 得到 0
  2. 异或运算也是一个考点
    • x^0 = x
    • x ^ x = 0

算法练习:四大算法设计**之一——贪心算法(Greedy)

题目列表

总结:

  1. 什么是贪心算法:在对问题求解时,总是做出在当前看来是最好的选择。
  2. 适用场景:适用贪心算法的场景就是,问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。
  3. 用贪心算法解决问题的思路,并不总能给出最优解。
  4. 典型案例:背包问题(注:不是0-1背包问题),分糖果,钱币找零,区间覆盖

算法练习:四大算法设计**之三——回溯算法(Backtracking)

题目列表

总结

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.