LeetCode刷题套路

一.Array题型

1.Two Pointers

Two Pointers同向:其中[0,i)的数据代表处理好的数据,[i,j)中的数据是那些处理过但不需要的数据,[j,array.length)区间的数据为接下来待处理的数据。这里的三个区间的开和闭需要根据题目要求定义,但是要保持一致。用此方法处理过的数组,处理好的数据的相对位置会保持一致

通用步骤

①initialize two pointers i and j,usually both equal to 0

②while j <array.length:

    if we need array[j],then we keep it by assigning array[i] = array[j], and move i forward, make it ready at the next position

    otherwise skip it. We do not need to move i since its spot is not fullfilled

Two Pointers反向:其中[0,i)和(j,array.length)内的数据均为处理好的数据,[i,j]中的数据待处理。用此方法处理过的数组不会保留原来元素的相对位置

通用步骤

①initialize two pointers i =0, j=array.length -1

②while i <j:

    Decide what you should do based on the value of array[i] and array[j]

    Move at least one pointer forward in its direction

练习题

11.盛最多水的容器

26.删除有序数组中的重复项

42.接雨水

80.删除有序数组中的重复项 II

283.移动零

344.反转字符串

1047.删除字符串所有相邻重复项

2.Binary Search

是一种针对有序区间内的O(logN)搜索方式,最常见用于已经排好序的Array

两大基本原则

每次都要缩减搜索区域

每次缩减不能排除潜在答案

找一个准确值

循环条件:l ≤ r

缩减搜索空间:l = mid +1,r=mid -1

找一个模糊值(比2大的最小数)

循环条件:l<r

缩减搜索空间:l = mid,r = mid-1或者l = mid +1,r=mid

万用型(最接近2的数)

循环条件:l<r-1

缩减搜索空间:l = mid,r = mid

练习题

410.分割数组的最大值

852.山脉数组的峰顶索引

1011.在D天内送达包裹的能力

1062.最长重复子串

1231.分享巧克力

1292.元素和小于等于阈值的正方形的最大边长

二.Liked List题型

Liked List vs. Array

Array:一组内存里连续的数据

能用index访问 → O(1) Access

添加元素直接添加在最后 → Amortized O(1) Add(考虑到扩容)

删除元素需要挪动后面所有元素位置 → O(n) Delete

Linked List:内存里不一定连续的数据

不能用index访问 → O(n) Access

添加元素添加在最后 → O(n) Add,双链表O(1)

删除元素需要找到元素位置 → O(n) Delete

1.Two Pointers

两个指针指向Linked List节点,不再是index

两个指针必定同向而行

①一个快一个慢,距离隔开多少

②两个指针移动速度

2.Recursion递归

Bottom up recursion 3 steps:

①Ask for subproblem result

②Do something in current level of recursion

③Return result

第1,3步的值的含义必须相同

Recursion最重要的一点:相信自己的recursive function是对的

三.Stack题型

特性:LIFO (Last In First Out)

适用于需要记录之前的状态,必要的时候可以回到之前的状态,或者利用之前的值

不像array,不能用index访问,只能每次拿栈顶元素

题外话:动态规划Dynamic Programming

DP:记录之前所有状态,随时可能访问任何一个子问题,所以通常用Array或者Hash Table,而且不会回到之前的状态,只会利用之前的值

Stack:每次只需要栈顶元素,并且每个状态只会被用O(1)次

定义好Stack的含义

在arr[i]左侧所有比arr[i]大的数

递归之前的函数状态(Call Stack)

练习题

20.有效的括号

84.柱状图中最大的矩形

394.字符串解码

496.下一个更大元素 I

503.下一个更大元素 II

636.函数的独占时间

735.行星碰撞

739.每日温度

四.Heap题型

Heap本质是一个用Array实现的Complete Binary Tree,这个Tree的root节点代表整个Heap里的最大或最小值

Common APIs:

peek() → 查看堆顶元素O(1)

poll() → 拿出堆顶元素O(logN)
offer() → 添加元素O(logN)

Online Algorithm(using Heap):

针对一组流数据,没有固定长度,可以随时根据需求scalable

Offline Algorithm(using Sorting):

针对一组固定长度数据,每次scale后要重新计算

练习题

23.合并K个升序链表

215.数组中的第K个最大元素

253.会议室 II

295.数据流的中位数

347.前K个高频元素

703.数据流中的第K大元素

767.重构字符串

五.HashMap题型

HashMap

用Array + LinkedList(chaining)实现的能在平均O(1)时间内快速增删查的数据结构

表内存储的数据需要实现equals()和hashCode()

LinkedHashMap

有顺序的hashmap,遍历顺序是key插入的顺序

所有的key按顺序存成一个LinkedList

TreeMap

有顺序的map,遍历顺序是key从小到大

所有的key存成一个红黑树(self-balancing binary tree)

增删查O(logN)

HashSet

没有value的HashMap

什么时候用HashMap?

当需要快速查找数据时,可以利用HashMap加速查找

主要要查找的数据结构实现了equal()和hashCode()

Array和HashMap的区别在于:Array无法快速查找,HashMap可以;Array里的元素是有顺序的,HashMap没有;Array的overhead比较小,HashMap实现比较复杂

练习题

1.两数之和

3.无重复字符的最长子串

49.字母异位词分组

138.复制带随机指针的链表

535.TinyURL的加密与解密

554.砖墙

560.和为K的子数组

六.Tree题型

类似LinkedList的概念,内存中不一定连续的数据,由各个节点的Reference串起来组成

节点可以分为Parent和Child两类

可以看做一个特殊的无环无向图

只有一个入口root

99%Tree的题目都是没有parent指针的Binary Tree

1.BFS(宽度优先搜索)

是按层的概念进行的搜索算法,利用Queue记录需要被展开的TreeNode

适合解决与层数相关的Tree题目

①Initialize Queue with all entry points

②While queue is not empty

   for each node in the queue(currently)

   poll out the element(add to result)

   expand it,offer children to the queue in order

   increase level

每个Node进出Queue一次 → O(n)

练习题

101.对称二叉树

102.二叉树的层序遍历

103.二叉树的锯齿形层序遍历

104.二叉树的最大深度

111.二叉树的最小深度

429.N叉树的层序遍历

515.在每个树行中找最大值

2.DFS(深度优先搜索)

DFS是一种递归形式的搜索方式,更偏向于“垂直”的概念

①Base Case

②DoSomething

③Recurse for subproblems

Top Down DFS

把值通过参数的形式从上往下传

一般dfs本身不返回值

①Base Case

②利用父问题传下来的值做一些计算

③若有必要,做一些额外操作

④把值传下去给子问题继续递归

练习题

129.求根节点到叶节点数字之和

Bottom Up DFS(更难也更常见)

把值从下往上传

当前递归利用subproblem传上来的值计算当前层的新值并返回

一定会有返回值

①Base Case

②向子问题要答案(return value)

③利用子问题的答案构建当前问题(当前递归层)的答案

④若有必要,做一些额外操作

⑤返回答案(给父问题)

练习题

104.二叉树的最大深度

124.二叉树中的最大路径和

七.Graph题型

类似LinkedList的概念,内存中不一定连续的数据,由各个节点的Reference串起来组成

可能有环

分为有向图和无向图

没有固定入口

可能有多个入口

图该以什么形式存储?最常用的两大类:Adjacency Matrix和Adjacency List

Adjacency List

最常用的两种实现方式(List可用Set代替)

List<T>[n]

adjList[i]:All neighbors of node i

Need to know number of nodes(n) beforehand

Map<T,List<T>>

adjList.get(i):All neighbors of node i

1.BFS(Breadth - First Search)

以层为概念的搜索方式,因为是水平展开所有nodes,所以适合寻找最短路径

图可能有环,需要查重

①Initialize a Queue with all starting points,a HashSet to record visited nodes

②While queue is not empty

    Retrieve current queue size as number of nodes in the current level

    for each node in current level

         poll out one node

         if this is the node we want,return it

         offer all its neighbor to the queue if not visited and valid

     Increase level

小技巧:对于2D Matrix的图,matrix[i][j]的neighbors一般都是上下左右4个,所以预先存一个4 direction array可以帮助访问neighbors → directions = {{0,1},{1,0},{0,-1},{-1,0}}

Time Complexity O(V+E)

练习题

127.单词接龙

542.01矩阵

BFS(Best - First Search)

针对Non-uniform cost graph的一种算法,核心思想是优先展开最优的节点

如何每次快速计算最优 → Heap

最有名的graph中找最短路径的算法又称Dijsktra's Algorithm

①Initialize a Heap with all starting points marked with some initial costs, a HashSet to record visited nodes

②While heap is not empty

    poll out one node

    if it has already been expanded(visited),skip it

    otherwise mark the node as visited,update its cost

    if this is the destination node,return

    for all of its neighbors,offer them in to the heap with current node's cost + edge cost

Time: O((E+V)logV)    Space:O(V)

练习题

743.网络延迟时间

787.K站中转内最便宜的航班

2.DFS(Depth - First Search)

不同于BFS一层一层往外扩展,DFS会一口气扎到最深层再递归回到原点,然后再次一口气扎到另一条路的最深层,如此往复

①Initialize HashSet to record visited nodes

②For all entry nodes,call dfs():

   Validate current node,if visited or invalid or answer node,return

   Do something(pre-order)

   For each neighbor node:

          Validate neighbor node,if visited or invalid or answer node,don't recurse on it or return answer

          Recurse down on neighbor node → dfs(neighbor)

   Do something(post-order)

DFS traverse graph一般不允许访问同一节点非常数次,所以Time Complexity O(N*k),k=max(time(b),time(d))

练习题

133.克隆图

200.岛屿数量

332.重新安排行程

399.除法求值

785.判断二分图

841.钥匙与房间

八.DP题型

1.Search

当一个大问题是由多个子问题构成时,我们可以通过不断分解问题来最终构建我们想求的大问题,这个过程称为搜索

搜索空间可以用Tree的形式展现出来,便于理解

时间复杂度取决于这棵树的深度和每个node的children个数

Search最重要的就是定义好状态,保证每个子问题都能用一个状态来描述

练习题

78.子集

2.DP(Dynamic Programming)

如果我们Search Space有重复子问题的话,可以记录下这些子问题的答案来保证不会重复计算多次,所以DP也被称为Search+Memorization

如此一来,时间复杂度就取决于子问题的个数

搜索空间可以用Tree的形式展现出来,便于理解

所有DP都可以写成Bottom Up DFS的形式

重中之重仍然是定义好状态

小技巧:定义好状态后,可以从一个中间状态出发去思考递归规则

Bottom Up DFS

①Define state of subproblems

②initialize memo to record calculated subproblems

③return dfs(top_level_answer_state)

dfs(state):

①base case check

②if current problem is calculated,return its answer

③for each subproblem x

   ask subproblem for their answers → call dfs(subproblem_state)

   build up current state problem answer based on subproblem answers

④store current problem answer

练习题

139.单词拆分

3.1D Dynamic Programming

练习题

53.最大子数组和

91.解码方法

96.不同的二叉搜索树

140.单词拆分 II

279.完全平方数

303.区域和检索 - 数组不可变

338.比特位计数

343.整数拆分

4..2D Dynamic Programming

2D Array → state = (row,col)

2个1D Array → Each 1D state

1D Array + K → state = (i,k)

1D Array → 2D state (subarray)

练习题

5.最长回文子串

63.不同路径 II

123.买卖股票的最佳时机 III

188.买卖股票的最佳时机 IV

312.戳气球

322.零钱兑换

410.分割数组的最大值

516.最长回文子序列

873.最长的斐波那契子序列的长度

887.鸡蛋掉落

877.石子游戏

1000.合并石头的最低成本

1143.最长公共子序列

1216.验证回文字符串 III

1312.让字符串成为回文串的最少插入次数

1335.工作计划的最低难度

九.Backtrack题型

Backtrack是DFS的一种形式,基本写法类似于Top Down DFS,但是引入了状态回溯

每次搜索一个分支,会首先记录当前节点的状态,尝试完某一个分支后,把状态回溯到记录的状态,再去尝试另外的分支

为什么要回溯状态?如果不回溯,A分支的状态可能会被代入B分支,但他们又是独立的,所以会影响结果

①Base Case

②For each possibility p

    memorize current state

    backtrack(next_state)

    restore current state

练习题

46.全排列

47.全排列 II

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值