算法题
black f
落子无悔,不忘初心,日日精进,圣贤可达。
展开
-
单词拆分想法
class Solution {public: bool wordBreak(string s, vector<string>& wordDict) { unordered_set<string> wordDictSet(wordDict.begin(), wordDict.end()); vector<bool> dp(s.size() + 1, false); dp[0] = true;原创 2021-07-12 17:38:08 · 83 阅读 · 0 评论 -
复制带随机指针的链表
/*// Definition for a Node.class Node {public: int val; Node* next; Node* random; Node(int _val) { val = _val; next = NULL; random = NULL; }};*/class Solution {public: map<Node*, Node*> mp;原创 2021-07-08 20:46:27 · 51 阅读 · 0 评论 -
老师分发糖果
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:每个孩子至少分配到 1 个糖果。评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。那么这样下来,老师至少需要准备多少颗糖果呢?示例 1:输入:[1,0,2]输出:5解释:你可以分别给这三个孩子分发 2、1、2 颗糖果。示例 2:输入:[1,2,2]输出:4解释:你可以分别给这三个孩子分发 1、2、1 颗糖果。第三个孩子只得到 1 颗糖果,原创 2021-07-02 11:18:28 · 105 阅读 · 0 评论 -
克隆图(递归方法)
/*// Definition for a Node.class Node {public: int val; vector<Node*> neighbors; Node() { val = 0; neighbors = vector<Node*>(); } Node(int _val) { val = _val; neighbors = vector<Node*>原创 2021-06-22 20:38:45 · 59 阅读 · 0 评论 -
分割回文串 II
class Solution {public: int minCut(string s) { int sLen = s.length(); vector<vector<bool>> dp(sLen, vector<bool>(sLen, false)); for (int j = 0; j < sLen; ++j) { for (int i = j; i >= 0; --i)原创 2021-06-17 20:06:38 · 81 阅读 · 0 评论 -
被围绕的区域
class Solution {public: int m; int n; bool flag; vector<vector<bool>> isVisit; set<pair<int, int>> hasVisitO; void Dfs(int i, int j, vector<vector<char>>& board) { if (i < 0 |原创 2021-06-17 16:55:27 · 71 阅读 · 0 评论 -
最长连续序列
class Solution {public: int longestConsecutive(vector<int>& nums) { if (nums.size() == 0) { return 0; } sort(nums.begin(), nums.end()); // 保证循环内一定能找到结果 nums.emplace_back(INT_MAX);原创 2021-06-17 11:27:33 · 57 阅读 · 0 评论 -
单词接龙 II
按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> … -> sk 这样的单词序列,并满足:每对相邻的单词之间仅有单个字母不同。转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。sk == endWord给你两个单词 beginWor原创 2021-06-16 11:56:22 · 85 阅读 · 0 评论 -
二叉树中的最大路径和
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。路径和 是路径中各节点值的总和。给你一个二叉树的根节点 root ,返回其 最大路径和 。这道题用直接的想法,把每个节点都当做根节点,用一个全局变量记录最大值。注意返回给上一层的值只能包含一侧的分支。/** * Definition for a binary tree node. * struct TreeNode { *原创 2021-06-15 16:27:03 · 103 阅读 · 0 评论 -
填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:struct Node { int val; Node *left; Node *right; Node *next;}填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL。示例:输入:root = [1,2,3,4,5,6,7]输出:[1,#,2,3,#,4原创 2021-05-31 11:53:25 · 89 阅读 · 0 评论 -
树状数组基本使用
树状数组(Binary Index Tree, BIT)是很多OIer心中最简洁优美的数据结构之一。最简单的树状数组支持两种操作,时间复杂度均为 :单点修改:更改数组中一个元素的值区间查询:查询一个区间内所有元素的和树状数组就是这样一种结构,它巧妙地利用了二进制(实际上,树状数组的英文名BIT,直译过来就是二进制下标树)。那么如何更新呢,大家会发现更新就是一个“爬树”的过程。一路往上更新,直到MAXN(树状数组的容量)。树状数组的实现前面已经讲得很详细了,代码实现倒是一件简单的事了。不过我原创 2021-05-27 11:08:30 · 230 阅读 · 0 评论 -
并查集玩法
并查集被很多OIer认为是最简洁而优雅的数据结构之一,主要用于解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作:合并(Union):把两个不相交的集合合并为一个集合。查询(Find):查询两个元素是否在同一个集合中。处于同一集合的元素会组合成一颗树。最常见的问题是我的朋友的朋友 是 我的朋友。// 初始化的数据结构,下标表示元素,值表示该元素的父节点vector<int> fa(n, 0);for (int i = 0; i < n; ++i) { f原创 2021-05-25 19:34:42 · 56 阅读 · 0 评论 -
盒中取球
盒中有n个小球,A,B两人轮流取。约定:每个人从盒中取的球数必须是1,3,7,8。A、B轮流取球,直到取完。拿到最后一个球就算输。A先手,给定球数,在两人都不失误时,判断A最终是否能赢?球数 < 10000.刚看到这道题,突然想到一个BGM buttercup。取最后一个球的倒霉蛋拿到球是多么绝望o(╥﹏╥)o。动态规划,想办法让剩下的球朝着向自己有利的方向发展。#include<vector>int main(){ vector<int> dp(10000原创 2021-05-24 16:22:07 · 559 阅读 · 0 评论 -
不同的子序列
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,“ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)示例 1:输入:s = “rabbbit”, t = “rabbit”输出:3解释:如下图所示, 有 3 种可以从 s 中得到 “rabbit” 的方案。(上箭头符号 ^ 表示选取的字母)rabbbit^^^^ ^^rabbbit^原创 2021-05-23 17:02:47 · 88 阅读 · 0 评论 -
二叉树展开为链表
给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。其实也很好想,都告诉先序遍历了。所以每次遍历到一个节点,先把当前节点的左右子树存下来做递归。然后上一个节点的right 指向当前节点。再更新最新的插入节点。然后把当前root的左右子树置为null。/** * Definition for a binary tree n原创 2021-05-05 18:11:44 · 41 阅读 · 0 评论 -
判断是否是平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。很简单,后序遍历,逐层累加。然后做判断。class Solution {public: bool flag = true; int Recursion(TreeNode* root) { if (!flag) { return -1; } if (roo原创 2021-05-04 17:06:29 · 43 阅读 · 0 评论 -
从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。注意:你可以假设树中没有重复的元素。例如,给出前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7]返回如下的二叉树:思路也很简单,前序遍历的第一个元素一定是根元素,然后在中序遍历中找到该元素的下标。下标左边的一定是左子树,下标右边的一定是右子树。然后用递归搞定!/** * Definition for a binary tree node. * struct TreeNode {原创 2021-05-03 11:37:25 · 69 阅读 · 0 评论 -
二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。示例:二叉树:[3,9,20,null,null,15,7],返回其层序遍历结果:[[3],[9,20],[15,7]]其实很简单,中序遍历即可。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right;转载 2021-05-03 10:28:28 · 62 阅读 · 0 评论 -
验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:节点的左子树只包含小于当前节点的数。节点的右子树只包含大于当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。其实很简单,二叉搜索树对任意一个节点,左边的一定更小,右边的一定更大。所以中序遍历一定是一个升序数列。然后写代码!/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode原创 2021-04-23 11:46:12 · 50 阅读 · 0 评论 -
根据身高重建队列
假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。示例 1:输入:people = [[7,0],[4,4],[7原创 2021-04-22 17:23:24 · 45 阅读 · 0 评论 -
交错字符串
给定三个字符串 s1、s2、s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:s = s1 + s2 + … + snt = t1 + t2 + … + tm|n - m| <= 1交错 是 s1 + t1 + s2 + t2 + s3 + t3 + … 或者 t1 + s1 + t2 + s2 + t3 + s3 + …提示:a + b 意味着字符串 a 和 b 连接。示例1原创 2021-04-22 15:07:45 · 61 阅读 · 0 评论 -
不同的二叉搜索树2
给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?示例:这道题只让计数,并不需要给出树结构。所以如果直接用计算树结构的方法会超时。可以发现n的计算依赖于前面的结果,所以可以用动态规划法。设dp[i]为i个节点可以组成二叉搜索树的个数。且dp[0],dp[1] = 1。i = 2时,根节点固定,dp[2] = 左边0个节点个数 * 右边1个节点个数 + 左边1个节点个数 * 右边0个节点个数。依此类推…class Solution {public: int numTre原创 2021-04-22 11:47:59 · 35 阅读 · 0 评论 -
不同的二叉搜索树
给定一个整数 n,生成所有由 1 … n 为节点所组成的 二叉搜索树 。示例:输入:3输出:[[1,null,3,2],[3,2,null,1],[3,1,null,null,2],[2,1,3],[1,null,2,null,3]]提示:0 <= n <= 8首先明白什么是二叉搜索树,对任意一个节点,左边的元素比其小,右边的元素比其大。然后看题。真是懵逼,这是啥啊?但其实还是有技巧的。用递归 + 回溯。一步一步缩小问题规模,从而解决问题。/** * Defini原创 2021-04-22 10:59:13 · 64 阅读 · 0 评论 -
中序遍历
虽然很简单,还是记录一下啊!/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(原创 2021-04-21 20:25:39 · 70 阅读 · 0 评论 -
复原ip地址
给定一个只包含数字的字符串,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。你可以按任何顺序返回答案。有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。例如:“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效 IP 地址。示例 1:输入:s = “2552551113原创 2021-04-21 16:41:22 · 146 阅读 · 0 评论 -
解码方法
一条包含字母 A-Z 的消息通过以下映射进行了 编码 :‘A’ -> 1‘B’ -> 2…‘Z’ -> 26要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“11106” 可以映射为:“AAJF” ,将消息分组为 (1 1 10 6)“KJF” ,将消息分组为 (11 10 6)注意,消息不能分组为 (1 11 06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。给你一个只含数原创 2021-04-21 15:47:12 · 65 阅读 · 0 评论 -
一个整数数组的子集(递归中主动去重)
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。示例 1:输入:nums = [1,2,2]输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]示例 2:输入:nums = [0]输出:[[],[0]]我一开始做这道题的思路是,先对nums排序,再直接递归找到所有的组合数,然后用set去重。但显然这不是一个好方法,因为会搜索到无用的序列。另一种想法是当回溯做弹出原创 2021-04-21 15:05:56 · 245 阅读 · 0 评论 -
判断两个字符串包含的字符数是否相等
我们设定一个规则,abcd和dbca是相同的,因为他们字符数相同。一种想法是用map记录下来。但事实上,还可以对每个字符串做排序,排序后的字符串相等,则原串一定也是相等的。妙啊!原创 2021-04-21 09:45:46 · 257 阅读 · 0 评论 -
按特定值分隔链表
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。你应当 保留 两个分区中每个节点的初始相对位置。其实这道题直接的思路就可以做。首先要找到大于等于x的第一个值的前一个结点,作为插入位置的左边。然后再开始找小于x的节点做插入。注意每次插入后,插入位置的左边都要指向下一个元素,保证插入位置的右端不变。/** * Definition for singly-linked list. * struct ListNode原创 2021-04-20 20:58:55 · 69 阅读 · 0 评论 -
二维矩阵求最大矩形
给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。题目描述很简单。这里只介绍一种易于理解的方法。新建一个二维数组dp。dp中每个值表示,从当前位置开始往左数的1的个数。然后遍历矩阵,对每个位置,不断增加高度,宽度是高度包含数的位置的dp最小值。从而更新出最大面积。class Solution {public: int maximalRectangle(vector<vector<char>>&am原创 2021-04-20 20:07:42 · 941 阅读 · 0 评论 -
柱状图中最大的矩形
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。首先的想法当然是暴力破解法。遍历每个矩形。对每个矩形都左右扩展。直到高度比当前矩形低。然后用高坐标减低座标,再乘矩形高度。最后得到最大结果。然后是用栈的方法。使每个元素的底边尽可能长。以上面的输入为例。栈为空,push 2。之后是1,则2无法再向右扩展,且2向左扩展的最大值为弹出2后的栈顶元素下标(如果不存在栈顶元素,则最多扩展到0下标)。所以面积就有了。然后弹出2,原创 2021-04-20 15:45:42 · 70 阅读 · 0 评论 -
删除排序链表中的重复元素
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。返回同样按升序排列的结果链表。其实也很简单,人家怎么说,就怎么写。需要注意的是头节点也可能被干掉,所以要加一个假头节点。保证它一定不会被干掉,方便计算。/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; *原创 2021-04-20 11:19:58 · 51 阅读 · 0 评论 -
搜索二维矩阵
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:每行中的整数从左到右按升序排列。每行的第一个整数大于前一行的最后一个整数。这道题一看就是用两次二分查找。如果是java写的话,直接调用库,C++写的话,需要自己写二分查找。注意边界条件class Solution {public: bool searchMatrix(vector<vector<int>>& matrix, int target) { in原创 2021-04-03 22:28:07 · 58 阅读 · 0 评论 -
最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。示例 1:输入:s = “ADOBECODEBANC”, t = “ABC”输出:“BANC”示例 2:输入:s = “a”, t = “a”输出:“a”提示:1 <= s.length, t.length <= 105s 和 t 由英文字母组成这个题用滑动窗口的方法,原创 2021-04-02 17:30:55 · 88 阅读 · 0 评论 -
编辑距离-单词间转换
继续刷题给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。你可以对一个单词进行如下三种操作:插入一个字符删除一个字符替换一个字符示例 1:输入:word1 = “horse”, word2 = “ros”输出:3解释:horse -> rorse (将 ‘h’ 替换为 ‘r’)rorse -> rose (删除 ‘r’)rose -> ros (删除 ‘e’)示例 2:输入:word1 = “inten转载 2021-04-02 10:15:15 · 95 阅读 · 0 评论 -
电话号码的字母组合
电话号码有2 – 9。2上有abc…现在给出一串电话号码。求出所有的可能的字母组合。如:23,则组合有:ad,ae,af等9种。思路:这种带回溯的一看就用递归。细节上注意StringBuilder的用法和字符串遍历就行。class Solution { String[] alpha = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; String digits; StringBuilder sb = new原创 2021-04-02 10:13:47 · 171 阅读 · 0 评论 -
三数之和
给一个数组,找到全部的三数之和等于0。不能有重复的组合。方法一:暴力破解。方法二:先排序。然后固定第一个数,把第一个数相反数作为目标值,第二个数和第三个数分别初始化为第一个数之后的数组的前后两端值做遍历。实际写代码时要注意细节问题。import java.util.*;class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>原创 2021-04-01 14:27:31 · 40 阅读 · 0 评论 -
盛最多水的容器
给一个数组,找出两个数之间最多可以乘最多水。方法一:暴击破解方法二:双指针法。双指针固定于数组两端。向内移动较短边,因为此时限制面积的因素是较短边,直至双指针相遇。原创 2021-04-01 14:27:21 · 36 阅读 · 0 评论 -
正则表达式匹配问题
给定一个字符串s和一个字符规律p,写一个支持‘.’和‘’的正则表达式匹配。‘.’匹配任意单个字符‘’匹配零个or多个前面的那一个元素所谓匹配,是要涵盖整个字符串s,而不是部分字符串。s = aa p = a falses = aa p = a* trues = ab p = .* true思路:动态规划法,就是找到状态转移方程和边界条件。考虑全面很难,没做过类似的问题根本做不出来。另:只要是动态规划法,一般都能对空间复杂度做优化,本题也行。然后直接看代码:(未优化空间复杂度)原创 2021-04-01 14:27:07 · 126 阅读 · 0 评论 -
int类型超出范围
执行 int x = Integer.MAX_VALUE + 1;返回最小的负数。同理可得最大的正数。如果执行 (Integer.MIN_VALUE + 1000) * 1000, 会得到 1000000。又执行:(Integer.MIN_VALUE + 1000) * 459,得到 -2147024648。什么玩意。超范围不可控啊!有这样一道题,整数反转。输入: 123 输出 321 输入 -123 输出 -321, 如果反转后超出int范围,返回0。把代码记下来,一看便知:class So原创 2021-04-01 14:26:56 · 1753 阅读 · 0 评论