算法刷题记录 Day5
Date: 2024.02.26
leetcode 242. 有效的字母异位词 时间ON, 空间ON; 此题连续索引,用数组会更节省空间。
class Solution {
public:
bool isAnagram(string s, string t) {
unordered_map<char, int> dict;
for(const auto& a: s){
dict[a]++;
}
for(const auto& b: t){
if(dict.count(b) > 0){
dict[b]--;
}
else{
return false;
}
}
for(auto& it: dict){
if(it.second != 0){
return false;
}
}
return true;
}
};
leetcode 349. 两个数组的交集
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> s;
unordered_set<int> res;
for(int& n: nums1){
s.emplace(n);
}
for(int& n: nums2){
//if(s.count(n)){
//res.emplace(n);
//}
if(s.find(n)!= s.end()){
res.emplace(n);
}
}
return vector<int>{res.begin(), res.end()};
}
};
leetcode 202. 快乐数
class Solution {
public:
bool isHappy(int n) {
unordered_set<int> s;
int count = 0;
while(n != 1){
while(n != 0){
int tmp = n%10;
n = n/10;
count += tmp * tmp;
}
if(s.find(count) != s.end()){
return false;
}
else{
s.emplace(count);
n = count;
count = 0;
}
}
return true;
}
};
leetcode 1. 两数之和
// 暴力 时间ON^2, 空间O1
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0; i<nums.size(); i++){
for(int j=i+1; j<nums.size(); j++){
if(nums[i]+nums[j] == target){
return vector<int>{i, j};
}
}
}
return vector<int>{-1, -1};
}
};
// 哈希存储已访问元素。时间ON, 空间ON;
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> dict;
for(int i=0; i<nums.size(); i++){
if(dict.find((target-nums[i])) == dict.end()){
dict.emplace(nums[i], i);
}
else{
return vector<int>{i, dict[target-nums[i]]};
}
}
return vector<int>{-1, -1};
}
};
leetcode 509. 斐波那契数列
//DP
class Solution {
public:
int fib(int n) {
if(n == 0)
return 0;
vector<int> dp(n+1, 0);
dp[1] = 1;
for(int i=2; i<n+1; i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
// 递归
class Solution {
public:
int f(int n){
if(n <= 1){
return n;
}
else{
return f(n-1) + f(n-2);
}
}
int fib(int n) {
return f(n);
}
};
leetcode 70. 爬楼梯
class Solution {
public:
int climbStairs(int n) {
if(n<=2)
return n;
vector<int> dp(n+1, 0); //爬到第n阶的方法数
dp[1] = 1; // 爬到第一阶,有一种
dp[2] = 2;
// dp[n] = dp[n-1] + dp[n-2];爬到第n阶,或是dp[n-1]再爬一阶,或是dp[n-2]再爬两阶
for(int i=3; i<=n; i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
leetcode 746. 使用最小花费爬楼梯
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int> dp(cost.size()+1, 0); //dp[i]代表到达第i阶所需要的最小体力花费。
// dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]), where i>1
dp[0] = 0;
dp[1] = 0;
for(int i=2; i<=cost.size(); i++){
dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]);
}
return dp[cost.size()];
}
};
leetcode 62. 不同路径 时间复杂度O(MN),空间复杂度O(MN)
PS: 因为是一行一行计算,可以用一维数组保存,节省空间。
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 0)); //dp[i][j]表示从(0, 0)到达坐标(i,j)的路径数
// 递推公式:dp[i][j] = dp[i-1][j] + dp[i][j-1];
// 初始化:最左和最上都仅有一条路径到达
for(int i=0; i<n; i++){
dp[0][i] = 1;
}
for(int i=0; i<m; i++){
dp[i][0] = 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];
}
};
leetcode 63. 不同路径II.
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& G) {
if(G[0][0] == 1){
return 0;
}
int m = G.size();
int n = G[0].size();
vector<vector<int>> dp(m, vector<int>(n, 0)); //dp[i][j]表示从(0,0)到(i,j)的路径数
//dp[i][j] = dp[i-1][j] + dp[i][j-1] if G=0, else dp[i][j] = 0;
// 初始化第一行和第一列
dp[0][0] = 1;
for(int i=1; i<m; i++){
if(G[i][0] == 0){
dp[i][0] = dp[i-1][0];
}
else{
dp[i][0] = 0;
}
}
for(int i=1; i<n; i++){
if(G[0][i] == 0){
dp[0][i] = dp[0][i-1];
}
else{
dp[0][i] = 0;
}
}
for(int i=1; i<m; i++){
for(int j=1; j<n; j++){
if(G[i][j] == 1){
dp[i][j] = 0;
}
else{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
return dp[m-1][n-1];
}
};