LEETCODE 刷题记录

文章目录

    • 岛屿问题
      • 200. Number of Islands
      • 305. Number of Islands II
      • 694. Number of Distinct Islands
      • 711. Number of Distinct Islands II
    • 回文数问题
      • 234. Palindrome Linked List
      • 131. Palindrome Partitioning
      • 132. Palindrome Partitioning II
      • 1246. Palindrome Removal
      • 5. Longest Palindromic Substring
      • 906. Super Palindromes
    • 括号问题
      • 22. Generate Parentheses
      • 32. Longest Valid Parentheses
      • 301. Remove Invalid Parentheses
    • 跳跳乐问题
      • 55. Jump Game
      • 45. Jump Game II
    • 旋转的排序数组问题
      • 33. Search in Rotated Sorted Array
      • 81. Search in Rotated Sorted Array II
      • 153 Find Minimum in Rotated Sorted Array
      • 154 Find Minimum in Rotated Sorted Array II
    • 方阵中寻找最大面积问题
      • 85. Maximal Rectangle
      • 221. Maximal Square
    • Single Number 问题
      • Single Number I II:
      • Single Number III
    • 图问题
      • 133. clone graph
      • 207. Course Schedule
      • 210. Course Schedule II
    • 有限状态机
      • 289. Game of Life
      • 65. Valid Number
    • 二叉树问题
      • 103.Binary Tree Zigzag Level Order Traversal
      • 236. Lowest Common Ancestor of a Binary Tree
      • 337. House Robber III
      • 95. Unique Binary Search Trees II
      • 99. Recover Binary Search Tree
      • 428. Serialize and Deserialize N-ary Tree
    • 中位数问题
      • 4. Median of Two Sorted Arrays
    • 链表问题
      • 148. Sort List
      • 23. Merge k Sorted Lists
      • 25. Reverse Nodes in k-Group
      • 链表求和,分为正序存放和逆序存放
    • 单词问题
      • Word Ladder
      • Word Search
      • Word Break
    • 买卖股票问题
      • 原问题
      • 心得
    • 单调栈问题
      • 84. Largest Rectangle in Histogram
    • 基本计算器
      • 224. Basic Caculator
      • 227. Basic Calculator II
      • 772. Basic Calculator III
    • 滑动窗口
      • 76. Minimum Window Substring
      • 424. Longest Repeating Character Replacement
      • 239. Sliding Window Maximum
    • 其他未归类问题
      • 395. Longest Substring with At Least K Repeating Characters
      • 347. Top K Frequent Elements
      • 312. Burst Balloons
      • 416. Partition Equal Subset Sum
      • 560. Subarray Sum Equals K
      • 48. Rotate Image
      • 300. Longest Increasing Subsequence
      • 324. Wiggle Sort II
      • 179. Largest Number
      • 15. 3Sum
      • 43. Multiply Strings
      • 54,59 spiral matrix
      • 89. Gray Code
      • 42. Trapping Rain Water
      • 128. Longest Consecutive Sequence
      • 218. The Skyline Problem
      • 57. Insert Interval
      • 164. Maximum Gap
      • 488. Zuma Game
      • 440. K-th Smallest in Lexicographical Order
      • 28. Implement strstr

岛屿问题

在由一片0组成的海洋中,飘着由1组成的陆地(此处0和1可以替换为任何两个不同的符号)。针对岛屿有着一系列问题:

200. Number of Islands

最基础的是这片海上有多少个岛屿?
DFS或者BFS都可以做,个人感觉DFS更好写一点。
代码:Number of Islands I

305. Number of Islands II

这次初始是一片海洋,题目会给一组坐标作为每次新增加的陆地。求每次增加陆地后的岛屿数。
暴力解法完全可以执行N轮问题200中的代码,但是这样的效率是很低的。因此需要用到一种常见的算法:并查集(Union Find)
给定一些点与点之间联通的情况,判断哪些点属于一个组中,不需要具体路径的时候,使用并查集就是比较好的。为了性能考虑我们采用带权值的树结构来存储点和群组。
代码:Number of Islands II

694. Number of Distinct Islands

在不考虑旋转映射等情况下,这片海上有多少个不同的岛屿呢?
在 Number of Islands基础上,只需要储存节点相对位置即可:
代码:Number of Distinct Islands

711. Number of Distinct Islands II

接着694问,如果此时考虑旋转等情况,这片海上又有多少不同的岛屿呢?
这个主要的问题在于如何建模,使得旋转镜像的图形都属于同一类。这个我参考了网上代码,思路是:
对694中得到的节点位置进行normalize,目的是变换成同一种岛屿形状的唯一表示。
对于每一个坐标位置,其实总共有8种变换可能:x和y都可以分别变为相反数,且也可以同时变为相反数,再加上其本身,这就4种了。同时,上面的每一种情况都可以交换x和y的位置,这样总共就有8中变换方法。
使用8个大小相同的数组来保存各自所有的点。对于每一种形状,都对其所有的点进行排序,然后将每个点的绝对坐标变为相对坐标,即每个点都减去排序后第一个点的坐标,最后再对这8个形状排个序。
只要是属于同一个岛屿的形状,最后都会得到一模一样的8个形状数组,为了简单起见,只选取第一个形状形状当作这同一种岛屿的模型代表。
代码:Number of Distinct Islands II

回文数问题

回文数是一个比较麻烦的处理点,性质是从前往后读和从后往前读的结果相同。

234. Palindrome Linked List

这是一个将回文数和链表结合起来的问题。可以用快慢指针找到中点,然后翻转后半链表去比较,完事将链表还原。

131. Palindrome Partitioning

这个的思路是顺位从开始到结尾判断是否是回文数,是则加入最后的表中
Palindrome Partitioning

132. Palindrome Partitioning II

与131不同,这次不需要给出全部的分割法,只需要给出需要分割的最小次数。
碰到类似的题,优先考虑DP。
思路是:
Palindrome Partitioning II

1246. Palindrome Removal

给出一个数组,最少删除几次就可以全部删完。如果有回味序列删一次就可以。
区间dp。主要是递推公式,见递推公式
Palindrome Removal

5. Longest Palindromic Substring

这个的思路是记录出现过的最长的回文数的位置和长度,同样是从0开始扩展。思路是寻找重复的单元找到重复单元两侧向外扩展寻找回文。
Longest Palindromic Substring

906. Super Palindromes

一个数当他自身是回文数,同时它的平方根(是整数)也是回文数的时候,我们称为超级回文数。求给定范围内的超级回文数。
回溯法应用,思路不是通过判断而是通过构造来找出满足的例子。
Super Palindromes

括号问题

涉及到左右括号匹配等一系列问题

22. Generate Parentheses

给出括号对数N,求出所有的有效表达式。
思路是记录有多少左括号,直到记录的括号数为0,然后类似回溯法生成即可。
Generate Parentheses

32. Longest Valid Parentheses

给出一个括号组成的string,找出最长的有效的括号对的长度。
利用一个栈来存储括号对应的pos,然后弹出匹配成功的段。最后利用一个循环确定最长的子串。
Longest Valid Parentheses

301. Remove Invalid Parentheses

给出一段括号字符串,移除最少的括号使得该字符串左右括号匹配。
思路是DFS,对每一个字符做加入或者不加入的判断,最终将结果保存在set中即可。
Remove Invalid Parentheses

跳跳乐问题

给定一个非负整数数组,最初定位在数组的第一个索引处。
数组中的每个元素表示该位置的最大跳转长度。以此衍生的一系列问题。

55. Jump Game

判断是否能够到达最后一个索引
用一个reach记录当前可以到达的最远距离,当i>reach意味着没办法从之前的路径到达之后的节点,所以认为是跳不过去。
jump game

45. Jump Game II

求从开始到结束最少跳几次
与之前的问题类似,也是采用一个记录当前到达的点最多是多少
jump game II

旋转的排序数组问题

一个排好序的数组,从某一个点切开旋转,得到的就是 Rotated Sorted Array。举例:[1,2,3,4,5]从3切开,得到[4,5,1,2,3]。以此衍生了一些问题。

33. Search in Rotated Sorted Array

给定要搜索的目标值。 如果在数组中找到则返回其索引,否则返回-1。
假设数组中不存在重复。算法的运行时复杂度必须为O(log n)。
这个思路很清晰,首先通过二分法找到旋转点,获得旋转点以后,我们可以以旋转点为offset取余,这样对我们来说,这个数组就和旋转前的数组没区别了。
Search in Rotated Sorted Array

81. Search in Rotated Sorted Array II

您将获得要搜索的目标值。 如果在数组中找到则返回true,否则返回false。
与33题不同的地方在于,这次的问题中数组是包含重复的元素的,也就是说在二分法处理问题的时候我们需要额外判断一种情况:left=mid=right。其他没有变化,时间复杂度为O(logN)
Search in Rotated Sorted Array II

153 Find Minimum in Rotated Sorted Array

无重复元素的旋转排序数组找最小值。33中找到的rot就是最小值

154 Find Minimum in Rotated Sorted Array II

和153同理,只不过额外判断当nums[mid] == nums[high]的情况
Find Minimum in Rotated Sorted Array

方阵中寻找最大面积问题

给出一个包含01的矩阵,判断里面最大的矩形的面积

85. Maximal Rectangle

DP问题,思路是分别用三个数组记录当前位置的高,左起始和右起始。最后算出来最大的区域面积。
Maximal Rectangle

221. Maximal Square

问题类似于上面的矩阵问题,只不过换成了求最大正方形面积。只需要在原代码基础上在最后计算面积时选择pow(min(right[i] - left[i], height[i]), 2);

Single Number 问题

Single Number I II:

一个int数组中,每个数都出现了k(k>1)次,其中有一个元素出现p(p>=1 && p%k != 0)次。求找出这个元素。

这类型的题在评论区有位大佬有总结,我把它翻译过来如下:

  1. 首先考虑特殊情况:只有一位bit
    为了统计数组中1出现的次数,我们需要一个m位的计数器。这个技术器有以下的性质:
    计数器有一个初始值,为了简单起见,置为0;
    对于数组中的每个输入,如果为0,计数器保持不变;
    对于数组中的每个输入,如果为1,计数器加1;
    为了保证计数器表示的值能大于等于k,所以 2 m 2^m 2m >= k,等式两边取对数:m >= logk。
    注意位操作与0进行运算时不会改变自己:x = x | 0 和x = x ^ 0
    xm要改变值的条件是,xm-1, …, x1和i都为1,对应的算术表达式为:xm = xm ^ (xm-1 & … & x1 & i)。没错,这就是我们找到的位操作方法。
    当计数器等于k时,我们需要一种重置机制把计数器重置为0。为了达到这个目的,我们申请一个变量mask,分别对计数器的每一位(xm, …, x1)和mask进行按位与操作,即xm = xm & mask, …, x1 = x1 & mask。如果我们能保证,只有当计数器的值等于k,并且统计的都是数组元素为1情况下,mask会为0,我们就达到了目的。
  2. 其次考虑一般情况:32bit的整数
    他们能“共同”管理这32个计数器。说是“共同管理”,是因为m的最小值满足m >= logk时,我们可以用m个32位的整数代替32个m位的计数器。
  3. 返回值
    返回什么值,现在已经很明显了,用二进制形式表示p’ = p % k,当 p j ′ p'_j pj = 1时,返回 x j x_j xj即可。总结起来,算法的时间复杂度为O(n * logk),空间复杂度为O(logk)。
    Single Number

Single Number III

这次是其中有两个元素出现了1次,其他都是出现两次。
代码逻辑如下:假设a,b是所求元素
首先通过^ 得到 r = a^b
a^ b的本质是保留了a,b中不相同的位保留下来。通过 r &(~(r-1))得到最右边1的位置,这个就可以把a,b分在不同的阵营。分别再做一次 ^ 得到最终结果。
single number III

图问题

133. clone graph

关于BFS和DFS的最基本的应用。
Clone Graph

207. Course Schedule

参加n门课程,课程之间有依赖关系(有向图),判断该有向图是否有环。

两种解决方案:
BFS:方法是重复寻找一个入度为0的顶点,将该顶点从图中删除(即放进一个队列里存着,这个队列的顺序就是最后的拓扑排序,具体见程序),并将该结点及其所有的出边从图中删除(即该结点指向的结点的入度减1),最终若图中全为入度为1的点,则这些点至少组成一个回路。

DFS:假设图以邻接矩阵表示,一条深度遍历路线中如果有结点被第二次访问到,那么有环。我们用一个变量来标记某结点的访问状态(未访问,访问过,其后结点都被访问过),然后判断每一个结点的深度遍历路线即可。

Course Schedule I

210. Course Schedule II

您必须参加总共n门课程,标记为0到n-1。
有些课程可能有先决条件,例如,要修课程0,你必须先修课程1,表示为一对:[0,1]
根据课程总数和先决条件对列表,返回完成所有课程所需的课程顺序。
只需要将入度为0的节点输出到数组中即可。

有限状态机

289. Game of Life

给定具有m×n个单元的矩阵,每个单元具有初始状态live(1)或dead(0)。每个单元格使用以下四个规则与其八个邻居(水平,垂直,对角线)进行交互:

  1. 任何活着的单元如果邻居少于两个的活单元就会死亡,由于人口不足造成的。
  2. 任何有两个或三个活着的邻居的活单元都会继续活在下一代。
  3. 任何有三个以上活着的邻居的活单元都会死亡,由于人口过多。
  4. 任何具有正好三个活邻居的死单元变成活单元,这是通过繁殖。

编写一个函数来计算给定其当前状态的矩阵的下一个状态(在一次更新之后)。通过将上述规则同时应用于当前状态中的每个细胞来创建下一个状态,其中出生和死亡同时发生。
要求原址操作。
这类问题可以采用有限状态机方式,同时保存旧的状态和新的状态来实现原址操作。
game of life

65. Valid Number

判断一个字符串是不是合法的数字表达式,DFA。
valid number

二叉树问题

二叉树是每个结点最多有两个子树的树结构。围绕二叉树会衍生出一系列问题

103.Binary Tree Zigzag Level Order Traversal

给定二叉树,返回其节点值的Z字形级别遍历。 (即,从左到右,然后从右到左进行下一级别并在之间交替)。
我给出的解法是,先把每一层输出出来,然后对奇数层的vector做一个reverse。讨论区给了一种更直接的方法,采用一个队列保存节点,弹出的时候则判断是应该正向输入还是逆向输入。
Binary Tree Zigzag Level Order Traversal

236. Lowest Common Ancestor of a Binary Tree

给出一个二叉树,找出所给两个节点的最小公共祖先(LCA)
有个关键的特性:如果待寻找的两个点出现在不同的子树中,那么当前节点就是我们要的最终结果。简化后的代码如下:
Lowest Common Ancestor of a Binary Tree

337. House Robber III

二叉树抢劫,不能抢劫相邻的节点(比如父节点和他的子节点),求能抢劫的最大钱数。
保存带上根节点的最大值和不带根节点的最大值即可。
House Robber III

95. Unique Binary Search Trees II

给定整数n,生成存储值1 … n的所有结构上唯一的BST(二叉搜索树)。
可以通过深度优先搜索(递归)解决这道题。
因为二叉查找树满足父节点的值大于左子节点的值,小于右子节点的值,所以我们可以:
(1) 从 N=1 开始构建二叉查找树,则它的左子树节点数为 0,右子树节点数为 n-1;
(2) N=2 时,左子树节点数为 1,右子树节点数为 n-2;
……
(n) N=n 时,左子树节点数为 n-1,右子树节点数 0。
而在第(1)步中,右子树继续执行上述循环,子树的子树又执行这个循环,最终,我们可以将子树节点数减少到 1,而一个节点只有一种排列方式,所以此时可以毫不犹豫地将结果返回给上一级。然后包含有两个节点的二叉树排列方式又被返回给上一级。……
依此类推,我们最后可以得到所有不同结构的二叉查找树。
Unique Binary Search Trees II

99. Recover Binary Search Tree

二叉搜索树中两个元素对调了,在不改变结构的情况下,纠正回来。
学习一下Morris Traversal。
思路如下:
BST中序遍历是升序,当出现降序时,说明是被交换了。
Recover Binary Search Tree

428. Serialize and Deserialize N-ary Tree

序列化与反序列化树。联动问题:297 序列化与反序列化二叉树。
N叉树的一个序列化方法是用括号表示当前节点的子树。
反序列化则是利用栈来还原树。
Serialize and Deserialize N-ary Tree

中位数问题

4. Median of Two Sorted Arrays

很简单的思路:保证分出来的两部分一样多的情况下(分割数组1的i固定,意味着分割数组2的j固定),判断是否满足中位数要求(中位数本质:给出一个划分,使得左右两边都小于(或大于)这个划分)。
findMedianSortedArrays

链表问题

148. Sort List

排序链表, O(n log n) 时间复杂度,O(1)空间复杂度。
只有一点,虽然想到归并排序的方法,但是把归并过程想复杂了,在讨论区看到一个简洁的归并,代码如下:
sort list

23. Merge k Sorted Lists

合并K个已排序列表,用优先队列来辅助。
Merge k Sorted Lists

25. Reverse Nodes in k-Group

K个一组来翻转链表,找到长度为k的节点后,记录对应的节点,翻转当前节点,向下一个节点继续做同样的处理方法。
Reverse Nodes in k-Group

链表求和,分为正序存放和逆序存放

逆序存放就是按部就班加起来,最后别忘了进位要新建一个节点。
正序则是利用栈来辅助。

单词问题

Word Ladder

给定两个单词(beginWord和endWord)和一个字典的单词列表,找到从beginWord到endWord的最短变换序列的长度,满足:

  • 一次只能更改一个字母。
  • 每个转换后的单词必须存在于单词列表中。 请注意,beginWord不是转换后的单词。

注意:

  1. 如果没有这样的转换序列,则返回0。
  2. 所有单词都有相同的长度。
  3. 所有单词仅包含小写字母字符。
  4. 您可以假设单词列表中没有重复项。
  5. 您可以假设beginWord和endWord是非空的并且不相同。

这个题思路上来说是比较简单的,双向BFS。理论上也是可以用DFS,但是可能会超时。
Word Ladder
在I的基础上,输出所有长度最短的序列。
同样是BFS的应用。具体分析注释在代码中。
Word Ladder II

Word Search

给一个2维的字母矩阵,判断所给的单词数组中哪些单词能够通过字母矩阵生成。
I 判断word是否能被字母矩阵生成,回溯法即可。
II 给一个单词列表,找出所有能被生成的单词。trie的应用是为了能够让拥有相同前缀的string在判断到达根节点以后同时加入到set。这个相比暴力的搜索法在拥有更多相同前缀的string时,效率要高得多。
Word Search II

Word Break

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
I 只需要判断能否切割。这个时候使用动态规划即可解决。
II 在 I 的基础上需要输出所有字符串的拆分方式
思路是:首先用一个hash表储存给定的字典wordD,构造一个hashmap用来储存当前字符串长度和输出字符串memo。构造一个函数dp。核心思想是通过动态储存来减少重复计算的浪费。
word break II

买卖股票问题

原问题

买卖股票的问题在leetcode上一共包含六个。问题分别描述如下:
每个题目都会给一个数组,其中第i个元素是第i天给定股票的价格。
121:购买之前必须出售股票。每天只允许完成一笔交易,求最大利润
122:购买之前必须出售股票。尽可能的进行交易,求最大利润
123:购买之前必须出售股票。最多能进行两次交易,求最大利润
188:购买之前必须出售股票。最多能进行k次交易,求最大利润
309:购买之前必须出售股票。尽可能的进行交易,但是卖出后的一天内不能交易,求最大利润。
714:条件和122相同,但是每次完成交易都需要付一笔交易费fee,求最大利润

心得

121,122,123,188其实是同一个问题的不同形式。其中以188是一般问题,121是k=1的情况,122是k= ∞ \infty 的情况,123则是k=2的情况。
先看一般问题的解法:

首先这个问题使用DP的核心表达式(子问题)为:

dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
              max(   选择 rest  ,           选择 sell      )
解释:今天我没有持有股票,有两种可能:
要么是我昨天就没有持有,然后今天选择 rest,所以我今天还是没有持有;
要么是我昨天持有股票,但是今天我 sell 了,所以我今天没有持有股票了。
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
              max(   选择 rest  ,           选择 buy         )
解释:今天我持有着股票,有两种可能:
要么我昨天就持有着股票,然后今天选择 rest,所以我今天还持有着股票;
要么我昨天本没有持有,但今天我选择 buy,所以今天我就持有股票了。

base case:
dp[-1][k][0] = dp[i][0][0] = 0 
//第i天没做交易,或者还没开始计时(第-1天),此时手上没有股票,利润都是0。
dp[-1][k][1] = dp[i][0][1] = -infinity 
// 第i天没做交易,或者还没开始计时(第-1天),此时手上有股票,不可能,用负无穷表示。

309的问题是在122的基础上,增加了每次购买之后需要冷却一天的要求。这使得基本的子问题稍微发生变化,在hold的时候,当第i天想要购买是,减去的是i-2天的hold值。
714则是在122的基础上加了交易费,每次卖出时加一笔费用。
Best Time to Buy and Sell Stock

单调栈问题

84. Largest Rectangle in Histogram

给出一系列不同高度的矩阵,求最大面积。
这个是一个单调栈思路,维护一个只保存一路递增的栈,在处理栈中元素时就能保证最大面积在其中。详细讲解和演示见这里
Largest Rectangle in Histogram

基本计算器

实现基本计算器来评估简单的表达式字符串。

224. Basic Caculator

表达式字符串仅包含非负整数,+, - 运算符和空格,左右括号。 整数除法应截断为零。

227. Basic Calculator II

表达式字符串仅包含非负整数,+, - ,*,/运算符和空格。 整数除法应截断为零。

772. Basic Calculator III

表达式字符串仅包含非负整数,+, - ,*,/运算符和空格,左右括号。 整数除法应向下截断。

我的解法是用到了stringstream,term 负责计算两个加减号之间的所有乘法的值,并在下一次读到加减号时,把结果加减在total上。括号则是按照栈来匹配每次调用子函数来计算括号中的内容,并返回结果修改原字符串。
227 是最基础的计算,不包含括号,可以直接用caculate_help解决。
224 是在227的基础上,只包含±,带括号,可以把主函数的乘除部分删去。
772 就是224 和 227 的合并。
代码:
Basic Calculator

另一种解法是依赖栈和运算符优先级解决,代码不放了。

滑动窗口

滑动窗口的共性:

  1. 窗口由两个指针构成,一个左指针left,一个右指针right,然后[left,right]表示的索引范围是一个窗口了。
  2. 右指针right的功能是用来扩展窗口:当窗口内的条件没有达到题目要求时,我们需要不断移动右指针right直到窗口内的条件第一次满足题目要求为止。
  3. 左指针left的功能是用来缩小窗口的:当窗口内的条件已满足题目条件或多于题目条件时(窗口溢出),我们缩小窗口,也就是左指针left需要右移直到窗口条件不满足为止。这时,我们需要记录当前窗口的大小,并更新目前为止满足条件的最小窗口记录。之后,再次扩展右指针right,使得窗口满足题目的条件。

76. Minimum Window Substring

给出字符串S和T,找出S中包含T中全部字母的最小子字符串。
类似问题,需要一个数组记录目标的变化情况,并将每次达到要求的子串长度和其实位置记录下来,这个count就是精髓
Minimum Window Substring

424. Longest Repeating Character Replacement

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
Longest Repeating Character Replacement

239. Sliding Window Maximum

详细解释见代码
Sliding Window Maximum

其他未归类问题

395. Longest Substring with At Least K Repeating Characters

查找给定字符串的最长子字符串T的长度(仅由小写字母组成),以便T中的每个字符出现次数不少于k次。
思路是这样的:逐位去寻找是否有合适的子串,并在找的过程中记录出现过的最大子串长度,如果找到了一个子串则没有必要检查它覆盖的子串。代码如下:
Longest Substring with At Least K Repeating Characters

347. Top K Frequent Elements

给一个非空的数组,求按照频率排序下来的前k个元素
我所首先想到的思路是优先队列,C++中priority_queue的使用。
看了讨论区的解答后,还发现一种比较好用的方法,桶排序:
Top K Frequent Elements

312. Burst Balloons

通过戳爆所有的气球,来获得最大硬币和。
只需要掌握一点:选择一个气球不戳爆,以他为分割点,左右两个序列是相互独立的。也就是说一个首位为I和J的序列,以中间为K的点分割,则该序列的最大值为:
max[I][J] = nums[I-1]*NUMS[K]*nums[J+1] + max[I][K-1] + max[K+1][J]
以这个作为动态规划的公式:
Burst Balloons

416. Partition Equal Subset Sum

给出一系列非负整数,求问他们能不能分成大小相同的两个组。比如[1,5,5,11]可以分成[1,5,5]和[11]
我的方法超空间了,记录讨论区一个大佬的解法:
用到了bitset作为数据结构,bitset里面有对这个结构的简单介绍。
通过移位操作记录之前每个数加了多少,在和自身或操作。bitset每一位代表是否能够取到对应位置的和。最后只需要看能不能找到所求值即可。这里说明的更加详细。
Partition Equal Subset Sum

560. Subarray Sum Equals K

给出一个数组,和整数k,求有多少个连续的子序列的和等于k
基本思路:如果累计总和,在索引 i 和 j 处相差 k,即 sum[i] - sum[j] = k,则位于索引 i 和 j 之间的元素之和是 k。

基于这些想法,可以使用了一个哈希表 unordered_map,它用于存储所有可能的索引的累积总和以及相同累加和发生的次数。我们遍历数组nums并继续寻找累积总和。每当我们遇到一个新的和时,我们在hashmap中创建一个与该总和相对应的新条目。如果再次出现相同的和,我们增加与map中的和相对应的计数。此外,对于遇到的每个总和,我们还确定已经发生 sum-k总和的次数,因为它将确定具有总和 kk的子阵列发生到当前索引的次数。我们将 count增加相同的量。
最终count就是结果
Subarray Sum Equals K

48. Rotate Image

in-place旋转图像。先reverse数组在对位交换,很巧妙。注意reverse一个二维数组只会反正高维,不会反转低维。
Rotate Image

300. Longest Increasing Subsequence

给出一个未排序的数组,找出最长增长子序列的长度
我们给出三个策略判断增加一个已存在的序列是否是安全的

  • 如果A[i]是所有lists中最小的,则开一个新的list,长度为1
  • 如果A[i]是所有lists中最大的,则扩展已有的lists
  • 如果不是以上两种情况,则clone并扩展所有最后一个元素小于A[i]的lists,同时销毁和扩展后lists同长度的lists

当计算最大长度时,则只需要计算末尾的元素即可。
Longest Increasing Subsequence
该问题可以联动类似题目334. Increasing Triplet Subsequence

324. Wiggle Sort II

给定一个未排序的数组nums,重新排序,使得nums [0] < nums [1] > nums [2] < nums [3] O(N)时间和/或O(1)额外空间

这个问题如果不考虑附加条件比较简单,只需要先排好序然后大小混着填即可。考虑到O(n)的时间复杂度和常量级别的空间复杂度就比较困难了。我看到评论区里面有人给出了一种基于“虚拟index”思想的方法。
这个方法的思路是首先利用nth_element找到中位数,然后#define A(i) nums[(1+2*(i)) % (n|1)]很巧妙,把给定数组按照先奇数后偶数的方式对应起来,
然后通过交换方法让左边的奇数位全部都是大于median的数,右边则全部是小于median的数,这样相应的原来的数组中顺序就是wiggle的。可以说是很巧妙了。
Wiggle Sort II

179. Largest Number

给定一个非负整数列表,将它们排列成最大数字。
我一开始的想法是利用基数排序,对于高位相同的数来说,位数少的优先,但这样实现起来很复杂,讨论区给出了一种简单的方法。其实思路很简单,不对数字排序,而是对转化后的字符串排序,利用sort函数 自己写一个比较器,这样会简洁的多。
Largest Number

15. 3Sum

给定n个整数的数组nums,是否有元素a,b,c在nums中,a + b + c = 0? 找到数组中所有唯一的三元组,它们的总和为零。
解决方案集不得包含重复的三元组。

这个问题,我一上来准备使用暴力方法,利用multiset解决重复问题,显然时间复杂度为O( N 3 N^3 N3)是行不通的。因此评论区给了一个方法,思路是:先对数组进行排序,排好序之后再固定一个元素的情况下,分别从前后两端开始查找。
3sum

43. Multiply Strings

给出两个用字符串表示的数字,返回用字符串表示的这两个数字的乘积。
关键的一点:当前位置可以由序号和相同的乘法加起来决定的。
Multiply Strings

54,59 spiral matrix

这两个问题都是螺旋矩阵的问题,对于这类问题的处理有一个通用的解法。这里将59的代码放下面:
spiral matrix

89. Gray Code

格雷码是二进制数字系统,其中两个连续值仅在一位上不同。
给定代表代码中总位数的非负整数n,打印格雷码序列。 格雷码序列必须以0开头。
问题的突破点在于格雷码生成特性:输入为n的格雷码,后 2 n − 1 2^n-1 2n1元素的值 = 前 2 n − 1 2^n-1 2n1的元素的值的逆序 + 2 n − 1 2^{n-1} 2n1
Gray Code

42. Trapping Rain Water

给一个N个非负元素的数组,代表高度,求下雨时能积多少水。

其实该问题还有别的解决思路,也就是积累法:分别维护一个maxleft和maxright,将整个池子想象成一个大的水池,不断抬高边界高度即可。
Trapping Rain Water

128. Longest Consecutive Sequence

给一个乱序数组,找到其中连续最长的序列的长度。比如[100,2,65,1,3],结果是3([1,2,3])。复杂度O(N)

这个问题我想的没问题,但是写起来的时候空间用多了,导致修改了很久。核心的思想是:维护一个哈希表unordered_map,用来记录数组中的数和对应的最大连接长度。只需要维护最长连接数组的两端即可。
Longest Consecutive Sequence

218. The Skyline Problem

给出一系列长方形的起始坐标,终点坐标和高度,获得整个图形的轮廓坐标。
方法是描线法。将端点分为左右两个端点处理,每当最大高度不同时,即为转折点,保存下来。具体分析见代码。
The Skyline Problem

57. Insert Interval

给定一组非重叠间隔,在间隔中插入新间隔(必要时合并)。
分析见代码注释。
Insert Interval

164. Maximum Gap

给一个未排序数组,返回它在排好序的时候,连续两个元素之间的最大差值。
这个问题用到了桶排序,核心要点是最大gap的下界是(maxV - minV )/ (sSize - 1)。依照这个思路简化我们需要计算的部分,从而时间复杂度是O(2N+K),K是桶的数目,空间复杂度是O(3K)。满足时空复杂度为线性的要求。
Maximum Gap

488. Zuma Game

回溯+剪枝的应用。
Zuma Game

440. K-th Smallest in Lexicographical Order

构建一个十叉树,很巧妙
K-th Smallest in Lexicographical Order

28. Implement strstr

KMP算法的一个学习。
strstr

你可能感兴趣的:(代码知识梳理)