Leetcode刷题笔记--Hot21-30

目录

1--全排列(46)

2--旋转图像(48)

3--字母异位词分组(49)

4--最大子数组和(53)

5--跳跃游戏(55)

6--合并区间(56)

7--不同路径(62)

8--最小路径和(64)

9--爬楼梯(70)

10--编辑距离(72)


1--全排列(46)

主要思路1:

        经典全排列,每次枚举每一位时,重头开始枚举,用一个访问数组记录当前已经被访问过的数字;

        这道题不包含重复数字,所以不需要进行树层上的剪枝;

#include <iostream>
#include <vector>class Solution {
public:std::vector<std::vector<int>> permute(std::vector<int>& nums) {if(nums.size() == 0) return res;std::vector<bool> vis(nums.size(), false);std::vector<int> tmp;dfs(nums, vis, tmp);return res;}void dfs(std::vector<int>& nums, std::vector<bool>& vis, std::vector<int> &tmp){if(tmp.size() == nums.size()){res.push_back(tmp);return;}for(int i = 0; i < nums.size(); i++){if(vis[i] == true) continue;tmp.push_back(nums[i]);vis[i] = true;dfs(nums, vis, tmp);// 回溯tmp.pop_back();vis[i] = false;}}
private:std::vector<std::vector<int>> res;
};int main(int argc, char *argv[]){std::vector<int> test = {1,2,3};Solution S1;std::vector<std::vector<int>> res = S1.permute(test);for(auto v : res){for(auto i : v) std::cout << i << " ";std::cout << std::endl;}
}

主要思路2:

        可以利用下一个排列的思想来枚举全排列,首先需要将数组进行从小到大排序,然后不断求解下一个排列,一个下一个排列就是一个新的排列,直到最大的排列为止;

#include <iostream>
#include <vector>
#include <algorithm>class Solution {
public:std::vector<std::vector<int>> permute(std::vector<int>& nums) {if(nums.size() == 0) return res;std::sort(nums.begin(), nums.end()); // 从小到大排列res.push_back(nums); // 记录最小的排列while(nextp(nums)){res.push_back(nums);}return res;}bool nextp(std::vector<int>& nums){int n = nums.size();// 找到第一个顺序对int i;for(i = n - 2; i >= 0; i--){if(nums[i] < nums[i+1]) break;}if(i == -1) return false; //已经是最大排列了// 找到一个nums[j] > 上面的nums[i]int j;for(j = n - 1; j > i; j--){if(nums[j] > nums[i]) break;}// 交换nums[i] 和 nums[j]std::swap(nums[i], nums[j]);// 反转num[i+1] ~ nums.end()std::reverse(nums.begin() + i + 1, nums.end());return true;}private:std::vector<std::vector<int>> res;
};int main(int argc, char *argv[]){std::vector<int> test = {1,2,3};Solution S1;std::vector<std::vector<int>> res = S1.permute(test);for(auto v : res){for(auto i : v) std::cout << i << " ";std::cout << std::endl;}
}

2--旋转图像(48)

主要思路:

         按层(圈)来旋转,对于坐标为(r, c)的值,其旋转后的坐标为(c, n - 1 - r),且每四个(上,右,下,左)为一个循环节,循环交换循环节中四个元素即可,视频讲解参考:旋转图像

#include <iostream>
#include <vector>
#include <algorithm>class Solution {
public:void rotate(std::vector<std::vector<int>>& matrix) {int n = matrix.size();// 按层(圈)处理for(int L = n; L > 0; L -= 2){// 左上角起始元素int row = (n - L) / 2;int col = row;// 当前这一行,顶行的前 L-1 个元素for(int k = 0; k < L - 1; k++){// 当前元素int r = row, c = col + k;int tmp = matrix[r][c];// 从(r, c)开始寻找循环节,循环节的长度一定是4for(int i = 0; i < 4; i++){// 旋转后的坐标int rr = c;int cc = n - 1 - r;// 旋转std::swap(tmp, matrix[rr][cc]);r = rr;c = cc;}}}}
};
int main(int argc, char *argv[]){std::vector<std::vector<int>> test = {{1,2,3}, {4,5,6}, {7,8,9}};Solution S1;S1.rotate(test);for(auto v : test){for(auto i : v) std::cout << i << " ";std::cout << std::endl;}
}

3--字母异位词分组(49)

主要思路:

        字母异位词排序后肯定相同,因此将每个字符串按字符进行排序,将排序后的结果作为key,原字符串的集合作为value,通过哈希的方式将字母异位词存储在一次,最后遍历哈希表返回结果即可;

#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>class Solution {
public:std::vector<std::vector<std::string>> groupAnagrams(std::vector<std::string>& strs) {std::unordered_map<std::string, std::vector<std::string>> hash;for(const auto &str : strs){std::string key = str;std::sort(key.begin(), key.end()); // 字母异位词的排序顺序肯定相同hash[key].push_back(str);}std::vector<std::vector<std::string>> res;for(auto item : hash){ // 遍历哈希表res.push_back(item.second);}return res;}
};
int main(int argc, char *argv[]){std::vector<std::string> test = {"eat", "tea", "tan", "ate", "nat", "bat"};Solution S1;std::vector<std::vector<std::string>> res = S1.groupAnagrams(test);for(auto item : res){for(std::string str : item) std::cout << str << " ";std::cout << std::endl;}
}

4--最大子数组和(53)

主要思路:

        有点类似于一个滑动窗口(一般需要维护左右边界指针,但本题可以只维护右边界的指针),当滑动窗口内的和为正数时,右边界贪心地去纳入下一个数;

        当纳入下一个数时导致滑动窗口内的和为负数时,舍弃该滑动窗口并将当前的和置为0,接着从下一个数重新开始纳入新的值;

#include <iostream>
#include <vector>class Solution {
public:int maxSubArray(std::vector<int>& nums) {if(nums.size() == 1) return nums[0];// 初始化int max_sum = nums[0];int sum = 0;for(int i = 0; i < nums.size(); i++){// 尝试贪心地纳入新的一个值int cur_sum = sum + nums[i];// 当前滑动窗口内的和为正数,更新滑动窗口的和if(cur_sum > 0) sum = cur_sum;// 当前滑动窗口内的和为负数,抛弃前缀和为负数的结果else sum = 0; // 更新最大值if(cur_sum > max_sum) max_sum = cur_sum;}return max_sum;}
};int main(int argc, char *argv[]){std::vector<int> nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4};Solution S1;int res = S1.maxSubArray(nums);std::cout << res << std::endl;
}

5--跳跃游戏(55)

主要思路:

        维护一个滑动窗口,遍历数组的每一个元素,判断当前滑动窗口能到达的最大范围,当滑动窗口能够覆盖最后一个下标时,返回 true,否则返回 false;

#include <iostream>
#include <vector>class Solution {
public:bool canJump(std::vector<int>& nums) {int n = nums.size();int l = 0, r = 0;while(l < n - 1){int bound = l + nums[l];r = std::max(r, bound);if(l == r) break;l++;}return r >= n-1;}
};int main(int argc, char *argv[]){std::vector<int> nums = {2, 3, 1, 1, 4};Solution S1;bool res = S1.canJump(nums);if(res) std::cout << "true" << std::endl;else std::cout << "false" << std::endl;return 0;
}

6--合并区间(56)

主要思路:

        对数组进行排序,然后遍历数组,比较两者是否能合并,不能合并则存储上一区间,并从下一组重新开始判断,否则合并两个区间,继续判断下一组元素;

#include <iostream>
#include <vector>
#include <algorithm>class Solution {
public:std::vector<std::vector<int>> merge(std::vector<std::vector<int>>& intervals) {std::sort(intervals.begin(), intervals.end());int n = intervals.size();std::vector<std::vector<int>> res;int l = intervals[0][0], r = intervals[0][1];for(int i = 1; i < n; i++){if(intervals[i][0] > r){res.push_back({l, r});l = intervals[i][0];r = intervals[i][1];}else{r = std::max(r, intervals[i][1]);}}res.push_back({l, r}); // 存储最后一组return res;}
};int main(int argc, char *argv[]){// intervals = [[1,3],[2,6],[8,10],[15,18]]std::vector<std::vector<int>> test = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};Solution S1;std::vector<std::vector<int>> res = S1.merge(test);for(auto v : res){for(int item : v){std::cout << item << " ";}std::cout << std::endl;}return 0;
}

7--不同路径(62)

主要思路:

        比较直观的思路是使用递归的方法,向下和向右深度搜索能否到达右下角,但在本题中这种解法会超时;

#include <iostream>
#include <vector>// 递归
class Solution {
public:int uniquePaths(int m, int n) {dfs(0, 0, m, n);return res;}void dfs(int start_i, int start_j, int m, int n){if(start_i >= m || start_j >= n){return;}if(start_i == m - 1 && start_j == n - 1){res += 1;return;}dfs(start_i + 1, start_j, m, n);dfs(start_i, start_j + 1, m, n);}private:int res = 0;
};int main(int argc, char *argv[]){// m = 3, n = 7int m = 3, n = 2;Solution S1;int res = S1.uniquePaths(m, n);std::cout << res << std::endl;return 0;
}

主要思路:

        基于动态规划,定义状态 dp[i][j] 表示到达 (i,j) 坐标时的路径总数;

        状态转移方程:dp[i][j] = dp[i - 1][j] + dp[i][j-1];

        初始状态:上边界dp[0][j] = 1,左边界dp[i][0] = 1;

#include <iostream>
#include <vector>// 动态规划
class Solution {
public:int uniquePaths(int m, int n) {std::vector<std::vector<int>> dp(m, std::vector<int>(n, 0));for(int i = 0; i < m; i++){dp[i][0] = 1;}for(int j = 0; j < n; j++){dp[0][j] = 1; }for(int i = 1; i < m; i++){for(int j = 1; j < n; j++){dp[i][j] = dp[i-1][j] + dp[i][j-1];}}return dp[m-1][n-1];}
};int main(int argc, char *argv[]){// m = 3, n = 7int m = 3, n = 2;Solution S1;int res = S1.uniquePaths(m, n);std::cout << res << std::endl;return 0;
}

8--最小路径和(64)

主要思路:

        类似于上题,可以使用动态规划的方式进行求解,状态 dp[i][j] 表示经过到达坐标点 (i, j) 路径的最小和;

        状态转移方程:dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j];

        初始状态:dp[0][0] = grid[0][0],上边界dp[0][j] = dp[0][j-1] + grid[0][j],左边界dp[i][0] = dp[i-1][0] + grid[i][0];

#include <iostream>
#include <vector>// 动态规划
class Solution {
public:int minPathSum(std::vector<std::vector<int>>& grid) {int m = grid.size(), n = grid[0].size();std::vector<std::vector<int>> dp(grid.size(), std::vector<int>(grid[0].size(), 0));// 初始状态dp[0][0] = grid[0][0];for(int i = 1; i < m; i++){dp[i][0] = grid[i][0] + dp[i-1][0];}for(int j = 1; j < n; j++){dp[0][j] = grid[0][j] + dp[0][j-1]; }// 状态转移for(int i = 1; i < m; i++){for(int j = 1; j < n; j++){dp[i][j] = std::min(dp[i-1][j],  dp[i][j-1]) + grid[i][j];}}return dp[m-1][n-1];}
};int main(int argc, char *argv[]){// grid = [[1,3,1],[1,5,1],[4,2,1]]std::vector<std::vector<int>> test = {{1, 3, 1}, {1, 5, 1}, {4, 2, 1}};Solution S1;int res = S1.minPathSum(test);std::cout << res << std::endl;return 0;
}

        可以进一步将空间复杂度优化到O(1),直接在原数组中进行修改;

#include <iostream>
#include <vector>// 动态规划
class Solution {
public:int minPathSum(std::vector<std::vector<int>>& grid) {int m = grid.size(), n = grid[0].size();// 初始状态for(int i = 1; i < m; i++){grid[i][0] = grid[i][0] + grid[i-1][0];}for(int j = 1; j < n; j++){grid[0][j] = grid[0][j] + grid[0][j-1]; }// 状态转移for(int i = 1; i < m; i++){for(int j = 1; j < n; j++){grid[i][j] = std::min(grid[i-1][j],  grid[i][j-1]) + grid[i][j];}}return grid[m-1][n-1];}
};int main(int argc, char *argv[]){// grid = [[1,3,1],[1,5,1],[4,2,1]]std::vector<std::vector<int>> test = {{1, 3, 1}, {1, 5, 1}, {4, 2, 1}};Solution S1;int res = S1.minPathSum(test);std::cout << res << std::endl;return 0;
}

9--爬楼梯(70)

主要思路:

        经典动态规划easy题,定义状态 dp[i] 表示到达 i 阶楼梯时的方法数;

        状态转移方程:dp[i] = dp[i-1] + dp[i-2];

        初始状态:dp[0] = 1,dp[1] = 2;

#include "iostream"
#include <vector>class Solution {
public:int climbStairs(int n) {if(n == 1) return 1;std::vector<int> dp(n, 0);dp[0] = 1;dp[1] = 2;for(int i = 2; i < n; i++){dp[i] = dp[i-1] + dp[i-2];}return dp[n-1];}
};int main(int arc, char *argv[]){int n = 3;Solution S1;int res = S1.climbStairs(n);std::cout << res << std::endl;
}

10--编辑距离(72)

主要思路:

        基于动态规划,定义状态 dp[i][j] 表示 word1 前 i 个字符与 word2 前 j 个字符相等时的最少操作数;

        状态转移方程:当 word1[i] == word2[j] 时,dp[i][j] = dp[i-1][j-1];​​​​​当 word1[i] != word2[j] 时,dp[i][j] = min(dp[i-1][j-1]+1, dp[i-1][j]+1, dp[i][j-1]+1);

        初始状态:dp[0][0] = 0 表示两者都是空串,dp[i][0] = i 和 dp[0][j] = j 表示其中一个字符串为空;​​​​​​​

#include "iostream"
#include <vector>
#include <string>
#include <algorithm>class Solution {
public:int minDistance(std::string word1, std::string word2){int n = word1.size(), m = word2.size();std::vector<std::vector<int>> dp(n+1, std::vector<int>(m+1, 0));// 初始化dp[0][0] = 0; // 两者都是空串for(int i = 1; i <= n; i++) dp[i][0] = i; // 其中一个为空串for(int j = 1; j <= m; j++) dp[0][j] = j;// 状态转移for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){if(word1[i-1] == word2[j-1]){dp[i][j] = dp[i-1][j-1];} else{dp[i][j] = std::min(dp[i-1][j-1] + 1,std::min(dp[i][j-1]+1, dp[i-1][j]+1));}}}return dp[n][m];}
};int main(int arc, char *argv[]){// word1 = "horse", word2 = "ros"std::string word1 = "horse";std::string word2 = "ros";Solution S1;int res = S1.minDistance(word1, word2);std::cout << res << std::endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/109475.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初阶数据结构(五) 栈的介绍与实现

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn&#x1f493; ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的学习足迹&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 栈 栈的介绍栈的概念栈的结构 栈的实现…

数学系硕士研究生的科研过程——PDE约束下含参优化控制问题的深度学习算法

笔者今天上午收到了之前北大课题组老板的通知&#xff0c;得知研究生期间和学长合作的论文终于被siam接收&#xff0c;终于为自己研究生涯画上了一个句号。这里打算分享一下个人的科研过程以及这篇论文的工作&#xff0c;即将读研或者打算读研的同学或许可以从中获得益处。论文…

01.sqlite3学习——数据库概述

目录 重点概述总结 数据库标准介绍 什么是数据库&#xff1f; 数据库是如何存储数据的&#xff1f; 数据库是如何管理数据的&#xff1f; 数据库系统结构 常见关系型数据库管理系统 关系型数据库相关知识点 数据库与文件存储数据对比 重点概述总结 数据库可以理解为操…

CrystalNet .Net VCL for Delphi Crack

CrystalNet .Net VCL for Delphi Crack VCL或更为人所知的可视化组件库是基于一个面向对象的框架&#xff0c;什么是用户对开发人员和事件的Microsoft Windows应用程序的接口。可视化组件库是用对象Pascal编写的。它主要是为使用Borland而开发的&#xff0c;它具有与Delphi以及…

手把手教你安装Git,萌新迈向专业的必备一步

手把手教你安装Git&#xff0c;萌新迈向专业的必备一步 一、版本控制系统是什么&#xff1f;1. 倒霉的小明2. 版本控制系统3. 常见的版本控制系统 二、GitLab 与 GitHub1. GitLab2. GitHub 三、Git安装1. 下载2. 安装3. 验证 四、初学使用1. 本地仓库2. 远程仓库-Github3. 远程…

特斯拉启动墨西哥建厂计划,引发台厂竞逐 | 百能云芯

特斯拉&#xff08;Tesla&#xff09;在墨西哥新工厂计划备受瞩目&#xff0c;据外媒报道&#xff0c;墨西哥的超级工厂似乎正在迈出实质性的步伐。包括鸿海集团、广达&#xff08;Foxconn&#xff09;、和大在墨西哥和美墨边境都计划扩大电动车零配件生产基地。 市场对特斯拉在…

计算机技术与软件专业技术资格(水平)考试----系统架构设计师

【原文链接】计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试----系统架构设计师 考试简介 计算机软件资格考试是由国家人力资源和社会保障部、工业和信息化部领导下的国家级考试。计算机软件资格考试既是职业资格考试&#xff0c;又是职称资格考试。考试合格…

教师如何有效地发放开学通知并收集签名回执?

老师在即将开学时&#xff0c;希望能够向家长发送开学通知&#xff0c;并确认家长已经收到通知。接下来教给各位老师如何完成这个需求的步骤&#xff1a; 好消息&#xff01;博主给大家争取到的易查分福利&#xff0c;只需要在注册时输入邀请码&#xff1a;xmt66&#xff0c;就…

<template></template>、<slot></slot>、slot-scope、v-slot傻傻分不清!他们究竟是干啥的???

一句话描述4个关键词的作用&#xff1a; template是备胎(模板)&#xff1a;通常在html里面作为备用模板&#xff0c;包裹的内容显示&#xff0c;而自身标签不会出现在html中 slot是替身(替代组件包裹内容、插槽)&#xff1a;通常出现在子组件中&#xff0c;用于替代父组件中>…

1268. 搜索推荐系统

链接&#xff1a; 1268. 搜索推荐系统 题解&#xff1a; class Solution { public: struct Trie {Trie() {end false;next.resize(26, nullptr);}bool end;std::set<std::string> words;std::vector<Trie*> next; };void insert_trie(const std::string& w…

计算机竞赛 基于大数据的时间序列股价预测分析与可视化 - lstm

文章目录 1 前言2 时间序列的由来2.1 四种模型的名称&#xff1a; 3 数据预览4 理论公式4.1 协方差4.2 相关系数4.3 scikit-learn计算相关性 5 金融数据的时序分析5.1 数据概况5.2 序列变化情况计算 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &…

C/C++ 个人笔记

仅供个人复习&#xff0c; C语言IO占位符表 %d十进制整数(int)%ldlong%lldlong long%uunsigned int%o八进制整型%x十六进制整数/字符串地址%c单个字符%s字符串%ffloat&#xff0c;默认保留6位%lfdouble%e科学计数法%g根据大小自动选取f或e格式&#xff0c;去掉无效0 转义符表…

java八股文面试[多线程]——线程的生命周期

笔试题&#xff1a;画出线程的生命周期&#xff0c;各个状态的转换。 5.等待队列(本是Object里的方法&#xff0c;但影响了线程) 调用obj的wait(), notify()方法前&#xff0c;必须获得obj锁&#xff0c;也就是必须写在synchronized(obj) 代码段内。与等待队列相关的步骤和图 …

攻防世界-Web_php_unserialize

原题 解题思路 注释说了flag存在f14g.php中&#xff0c;但是在wakeup函数中&#xff0c;会把传入的文件名变成index.php。看wp知道&#xff0c;如果被反序列话的字符串其中对应的对象的属性个数发生变化时&#xff0c;会导致反序列化失败而同时使得__wakeup 失效&#xff08;CV…

MySQL每日一练--销售管理系统

一&#xff0c;创建数据库SaleSys 二&#xff0c;在数据库SaleSys中创建3张表 品牌信息表&#xff08;brand&#xff09; BrandId --品牌编号&#xff0c;整型&#xff0c;自动增长&#xff0c;主键BrandName --品牌名称&#xff0c;字符型&#xff0c; 唯一约束 商品表…

7 集群基本测试

1. 上传小文件到集群 在hadoop路径下执行命令创建一个文件夹用于存放即将上传的文件&#xff1a; [atguiguhadoop102 ~]$ hadoop fs -mkdir /input上传&#xff1a; [atguiguhadoop102 hadoop-3.1.3]$ hadoop fs -put wcinput/work.txt /input2.上传大文件 [atguiguhadoop1…

【百草阁送书-第二期】一名阿里服务端开发工程师的进阶之路

文章目录 一、前言二、AI 时代&#xff0c;服务端开发面临新挑战三、服务端开发会被 AI 取代吗&#xff1f;四、知识体系化&#xff0c;构建核心竞争力五、业界首本体系化、全景式解读服务端开发的著作六、参与抽奖方式 一、前言 目前&#xff0c;资讯、社交、游戏、消费、出行…

C#__使用Thread启动线程和传输数据

class Program{static void Test(){Console.WriteLine("Start……");Thread.Sleep(2000); // 1s等于1000ms&#xff0c;暂停2sConsole.WriteLine("end");}static void Download(Object ob){string str ob as string; // 遍历传递过来的ob字符串Console.Wr…

leetcode 739. 每日温度

2023.8.28 本题用暴力双层for循环解会超时&#xff0c;所以使用单调栈来解决&#xff0c;本质上是用空间换时间。维护一个单调递减栈&#xff0c;存储的是数组的下标。 代码如下&#xff1a; class Solution { public:vector<int> dailyTemperatures(vector<int>&…

学习记录——FeatEnHancer

FeatEnHancer: Enhancing Hierarchical Features for Object Detection and Beyond Under Low-Light Vision 一种适用于任意低光照任务增强方法 ICCV 2023 提出了FeatEnHancer&#xff0c;一种用于低光照视觉任务的增强型多尺度层次特征的新方法。提议的解决方案重点增强相关特…