力扣022. 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
向下搜索要满足两个条件:
插入数量不超过n
可以插入 ) 的前提是 ( 的数量大于 )
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
int lc = 0, rc = 0;
dfs(res, "", n, lc, rc);
return res;
}
void dfs(vector<string>& res, string path, int n, int lc, int rc) {
if (rc > lc || lc > n || rc > n) return;
if (lc == rc && lc == n) {
res.push_back(path);
return;
}
dfs(res, path + '(', n, lc + 1, rc);
dfs(res, path + ')', n, lc, rc + 1);
}
};
作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/generate-parentheses/solution/ru-men-ji-bie-de-hui-su-fa-xue-hui-tao-lu-miao-don/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣079. 单词搜索
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false
思路: 其实类似N皇后的问题,都是此路不通则返回上一状态并继续尝试。
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
for(int i = 0; i < board.size(); i++){
for(int j = 0; j < board[0].size(); j++){
if(backtrack(board, word, 0, i , j)){ // 从二维表格的每一个格子出发
return true;
}
}
}
return false;
}
private:
bool backtrack(vector<vector<char>>& board, string& word, int wordIndex, int x, int y){
if( board[x][y] != word[wordIndex]){ // 当前位的字母不相等,此路不通
return false;
}
if(word.size() - 1 == wordIndex){ // 最后一个字母也相等, 返回成功
return true;
}
char tmp = board[x][y];
board[x][y] = 0; // 避免该位重复使用
wordIndex++;
if((x > 0 && backtrack(board, word, wordIndex, x - 1, y)) // 往上走 (此处多谢笑川兄指正)
|| (y > 0 && backtrack(board, word, wordIndex, x, y - 1)) // 往左走
|| (x < board.size() - 1 && backtrack(board, word, wordIndex, x + 1, y)) // 往下走
|| (y < board[0].size() - 1 && backtrack(board, word, wordIndex, x, y + 1))){ // 往右走
return true; // 其中一条能走通,就算成功
}
board[x][y] = tmp; // 如果都不通,则回溯上一状态
return false;
}
};
作者:geekwade
链接:https://leetcode-cn.com/problems/word-search/solution/hui-su-suan-fa-dai-ma-jian-ji-yi-dong-by-geekwade/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣093. 复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 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 地址。
class Solution {
private:
vector<string> result;// 记录结果
// startIndex: 搜索的起始位置,pointNum:添加逗点的数量
void backtracking(string& s, int startIndex, int pointNum) {
if (pointNum == 3) { // 逗点数量为3时,分隔结束
// 判断第四段子字符串是否合法,如果合法就放进result中
if (isValid(s, startIndex, s.size() - 1)) {
result.push_back(s);
}
return;
}
for (int i = startIndex; i < s.size(); i++) {
if (isValid(s, startIndex, i)) { // 判断 [startIndex,i] 这个区间的子串是否合法
s.insert(s.begin() + i + 1 , '.'); // 在i的后面插入一个逗点
pointNum++;
backtracking(s, i + 2, pointNum); // 插入逗点之后下一个子串的起始位置为i+2
pointNum--; // 回溯
s.erase(s.begin() + i + 1); // 回溯删掉逗点
} else break; // 不合法,直接结束本层循环
}
}
// 判断字符串s在左闭又闭区间[start, end]所组成的数字是否合法
bool isValid(const string& s, int start, int end) {
if (start > end) {
return false;
}
if (s[start] == '0' && start != end) { // 0开头的数字不合法
return false;
}
int num = 0;
for (int i = start; i <= end; i++) {
if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
return false;
}
num = num * 10 + (s[i] - '0');
if (num > 255) { // 如果大于255了不合法
return false;
}
}
return true;
}
public:
vector<string> restoreIpAddresses(string s) {
result.clear();
backtracking(s, 0, 0);
return result;
}
};
作者:carlsun-2
链接:https://leetcode-cn.com/problems/restore-ip-addresses/solution/qie-ge-wen-ti-du-ke-yi-yong-hui-su-sou-s-4dun/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
思路:
二叉搜索树特征,左子树所有节点的值<根节点的值<右子树节点的值
递归检查根节点是否将序列划分为左右子树
class Solution {
bool helper(vector<int>& post,int lo, int hi){
if(lo >= hi) return true; //单节点或空节点返回true
int root = post[hi]; //后序遍历序列最后的值为根节点的值
int l = lo;
while(l<hi && post[l]<root)
l++; //遍历左子树(值小于根),左子树序列post[lo, l);
int r = l;
while(r<hi && post[r]>root)
r++; //遍历右子树(值大于根),右子树序列post[l, r);
if(r != hi) return false;//若未将post[l, hi)遍历完,则非后序遍历序列 返回false
return helper(post, lo, l-1) && helper(post, l, hi-1); //递归检查左右子树
}
public:
bool verifyPostorder(vector<int>& postorder) {
return helper(postorder,0,postorder.size()-1);
}
};
作者:zoememo
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/solution/hou-xu-bian-li-di-gui-c-by-zoememo/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣329. 矩阵中的最长递增路径
给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你 不能 在 对角线 方向上移动或移动到 边界外(即不允许环绕)。
思路:记忆化深度优先搜索
class Solution {
public:
static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int rows, columns;
int longestIncreasingPath(vector< vector<int> > &matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return 0;
}
rows = matrix.size();
columns = matrix[0].size();
auto memo = vector< vector<int> > (rows, vector <int> (columns));
int ans = 0;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
ans = max(ans, dfs(matrix, i, j, memo));
}
}
return ans;
}
int dfs(vector< vector<int> > &matrix, int row, int column, vector< vector<int> > &memo) {
if (memo[row][column] != 0) {
return memo[row][column];
}
++memo[row][column];
for (int i = 0; i < 4; ++i) {
int newRow = row + dirs[i][0], newColumn = column + dirs[i][1];
if (newRow >= 0 && newRow < rows && newColumn >= 0 && newColumn < columns && matrix[newRow][newColumn] > matrix[row][column]) {
memo[row][column] = max(memo[row][column], dfs(matrix, newRow, newColumn, memo) + 1);
}
}
return memo[row][column];
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/ju-zhen-zhong-de-zui-chang-di-zeng-lu-jing-by-le-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣200. 岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
思路:深度优先遍历
遍历整个数组,遇到1,ans++,ans是记录岛的个数的
运行一下dfs函数,把这个岛所有陆地给我沉喽,这个岛全部的1变成0
等把grid全遍历完,grid就全是0了,再把ans输出,这个ans就是我们记录的岛的个数
注意:grid竟然是char类型的,所有1和0都要加单引号哦
class Solution {
void dfs(vector<vector<char>> &grid,int cur_i,int cur_j)
{
if(cur_i<0||cur_i==grid.size()||cur_j<0||cur_j==grid[0].size()||grid[cur_i][cur_j]=='0') return;
grid[cur_i][cur_j]='0';
int di[4]={0,0,1,-1};
int dj[4]={1,-1,0,0};
for(int index=0;index<4;index++)
{
dfs(grid,cur_i+di[index],cur_j+dj[index]);
}
return;
}
public:
int numIslands(vector<vector<char>>& grid) {
int ans=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]=='1')
{
ans++;
dfs(grid,i,j);
}
}
}
return ans;
}
};
作者:shang-hai-chao
链接:https://leetcode-cn.com/problems/number-of-islands/solution/po-shi-wu-hua-de-shen-du-you-xian-bian-li-by-shang/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣695. 岛屿的最大面积
给定一个包含了一些 0 和 1 的非空二维数组 grid 。
一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)
官方解法:
class Solution {
int dfs(vector<vector<int>>& grid, int cur_i, int cur_j) {
if (cur_i < 0 || cur_j < 0 || cur_i == grid.size() || cur_j == grid[0].size() || grid[cur_i][cur_j] != 1) {
return 0;
}
grid[cur_i][cur_j] = 0;
int di[4] = {0, 0, 1, -1};
int dj[4] = {1, -1, 0, 0};
int ans = 1;
for (int index = 0; index != 4; ++index) {
int next_i = cur_i + di[index], next_j = cur_j + dj[index];
ans += dfs(grid, next_i, next_j);
}
return ans;
}
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
int ans = 0;
for (int i = 0; i != grid.size(); ++i) {
for (int j = 0; j != grid[0].size(); ++j) {
ans = max(ans, dfs(grid, i, j));
}
}
return ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/max-area-of-island/solution/dao-yu-de-zui-da-mian-ji-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
个人解法:
class Solution {
public:
void dfs(vector<vector<int>>& grid,int m,int n,int& sum)
{
if(m<0||m>=grid.size()||n<0||n>=grid[0].size()||grid[m][n]==0) return;
grid[m][n]=0;sum++;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
for(int i=0;i<4;i++)
{
dfs(grid,m+dx[i],n+dy[i],sum);
}
return;
}
int maxAreaOfIsland(vector<vector<int>>& grid) {
int res=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]==1)
{
int sum=0;
dfs(grid,i,j,sum);
res=max(res,sum);
}
}
}
return res;
}
};
力扣395. 至少有 K 个重复字符的最长子串
给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。
class Solution {
public:
//分治:对于一个字符串来说,如果要求子串最少出现k次,那么如果某些字母出现的次数小于k,
//这些字母一定不会出现在最长的子串中,并且这些字母将整个字符子串分割成小段,这些小段有可能是最长的
//但是由于被分割了,还是要检查这一小段,如果某些字母出现的次数小于k,会将小段继续分割下去,
//比如字符串"aacbbbdc",要求最少出现2次,我们记录左右闭区间,,
//第一轮[0,7],处理"aacbbbdc",d只出现了一次不满足,于是递归解决区间[0,5]、[7,7]
//第二轮[0,5],处理"aacbbb", c只出现了一次不满足,于是递归解决区间[0,1]、[3,4]
//第二轮[7,7],处理"c", c只出现了一次不满足,不继续递归
//第三轮[0,1],处理"aa", 满足出现次数>=2,ret=2
//第三轮[3,4],处理"bbb", 满足出现次数>=2 ret=3;
int dfs(string& s,int l,int r,int k,int ret=0)
{
if(l>r) return 0;
unordered_map<char,int>cnt;
for(int i=l;i<=r;i++)
cnt[s[i]]++;
vector<int>pos;
pos.push_back(l-1);
for(int i=l;i<=r;i++)
if(cnt[s[i]]<k)
pos.push_back(i);
pos.push_back(r+1);
if(pos.size()==2)
return r-l+1;
for(int i=0;i<pos.size()-1;i++)
ret=max(ret,dfs(s,pos[i]+1,pos[i+1]-1,k));
return ret;
}
int longestSubstring(string s, int k) {
if(s.size()==0) return 0;
return dfs(s,0,s.size()-1,k);
}
};