算法专题:记忆搜索

参考练习习题总集

文章目录

  • 前置知识
  • 练习习题
    • 87. 扰乱字符串
    • 97. 交错字符串
    • 375. 猜数字大小II
    • 403. 青蛙过河
    • 464. 我能赢吗
    • 494. 目标和
    • 552. 学生出勤记录II
    • 576. 出借的路径数

前置知识

没有什么特别知识,只有一些做题经验。要做这类型的题目,首先写出暴力搜索,然后写出记忆搜索,大概就是这个流程。感觉说了一些废话。

练习习题

87. 扰乱字符串

TLE:(自己写的难蚌代码)

class Solution {
public:unordered_set<string> jh;bool isScramble(string s1, string s2) {func(s1,0,s1.size()-1);return jh.find(s2)!=jh.end();}void func(string s,int l,int r){if (l==r) {jh.insert(s);return;}for (int i=l;i<r;i++){func(s,l,i);func(s,i+1,r);string temp=s.substr(0,l)+s.substr(i+1,r-i)+s.substr(l,i-l+1)+s.substr(r+1,s.size()-1-r);func(temp,l,l+r-i-1);func(temp,r-i+l,r);}}
};

TLE:(一个较合适的思路)

class Solution {
public:bool isScramble(string s1, string s2) {if (s1==s2) return true;if (check(s1,s2)) return false;for (int i=1;i<s1.size();i++){string a=s1.substr(0,i),b=s1.substr(i);string c=s2.substr(0,i),d=s2.substr(i);if (isScramble(a,c) and isScramble(b,d)) return true;string e=s2.substr(0,s1.size()-i),f=s2.substr(s1.size()-i);if (isScramble(a,f) and isScramble(b,e)) return true;}return false;}bool check(const string & s1,const string & s2){int lb[26] {};for (int i=0;i<s1.size();i++)lb[s1[i]-'a']+=1;for (int i=0;i<s2.size();i++)lb[s2[i]-'a']-=1;for (int i=0;i<26;i++)if (lb[i]!=0) return true;return false;}
};

AC:(刚上手就放弃的屑)
temp[i][j][k]:从s1[i]开始k个字符,从s2[j]开始k个字符,是否互为扰乱串呢。(包括下标本身字符)。if (temp[i][j][len]!=0) return temp[i][j][len]==1;是关键这句删除就是上面那种解法。

class Solution {
public:vector<vector<vector<int>>> temp;string string1,string2;int n;bool isScramble(string s1,string s2) {if (s1.size()!=s2.size()) return false;string1=s1;string2=s2;n=s1.size();temp.resize(n,vector<vector<int>> (n,vector<int> (n+1,0)));return dfs(0,0,n);}bool dfs(int i,int j,int len){if (temp[i][j][len]!=0) return temp[i][j][len]==1;string a=string1.substr(i,len),b=string2.substr(j,len);if (a==b){temp[i][j][len]=1;return true;}if (check(a,b)){temp[i][j][len]=-1;return false;}for (int k=1;k<len;k++) {if (dfs(i,j,k) and dfs(i+k,j+k,len-k)){temp[i][j][len]=1;return true;}if (dfs(i,j+len-k,k) and dfs(i+k,j,len-k)){temp[i][j][len]=1;return true;}}temp[i][j][len]=-1;return false;}bool check(const string & s1,const string & s2){int lb[26] {};for (int i=0;i<s1.size();i++)lb[s1[i]-'a']+=1;for (int i=0;i<s2.size();i++)lb[s2[i]-'a']-=1;for (int i=0;i<26;i++)if (lb[i]!=0) return true;return false;}
};

97. 交错字符串

MLE:(第一反应还是暴搜)

class Solution {
public:string string1,string2;unordered_set<string> jh;bool isInterleave(string s1, string s2, string s3) {if (s1.size()+s2.size()!=s3.size()) return false;string1=s1;string2=s2;string string3;func(0,0,string3);return jh.find(s3)!=jh.end();}void func(int l1,int l2,string s){if (l1<string1.size())func(l1+1,l2,s+string1[l1]);if (l2<string2.size())func(l1,l2+1,s+string2[l2]);if (l1==string1.size() and l2==string2.size())jh.insert(s);}
};

TLE:(优化一下,怎么还是没有过啊,我要疯了)

class Solution {
public:string string1,string2,string3;unordered_set<string> jh;bool isInterleave(string s1, string s2, string s3) {if (s1.size()+s2.size()!=s3.size()) return false;string1=s1;string2=s2;string3=s3;string string4;func(0,0,string4);return jh.find(s3)!=jh.end();}void func(int l1,int l2,string s){if (l1<string1.size() and string1[l1]==string3[s.size()])func(l1+1,l2,s+string1[l1]);if (l2<string2.size() and string2[l2]==string3[s.size()])func(l1,l2+1,s+string2[l2]);if (l1==string1.size() and l2==string2.size())jh.insert(s);}
};

TLE:(继续优化,真是过不了一点啊,最后一点真是可恶,受不了了)

class Solution {
public:string string1,string2,string3;bool flag=false;bool isInterleave(string s1, string s2, string s3) {if (s1.size()+s2.size()!=s3.size()) return false;string1=s1;string2=s2;string3=s3;func(0,0);return flag;}void func(int l1,int l2){if (!flag){if (l1<string1.size() and string1[l1]==string3[l1+l2])func(l1+1,l2);if (l2<string2.size() and string2[l2]==string3[l1+l2])func(l1,l2+1);if (l1==string1.size() and l2==string2.size())flag=true;}}
};

AC:(嗨嗨嗨导这么久了终于给我导出来了)
temp[i][j]:从s1[i]开始剩余字符,从s2[j]开始剩余字符,能否组成剩余部分。(包括下标本身字符)

class Solution {
public:string string1,string2,string3;vector<vector<int>> temp;bool isInterleave(string s1, string s2, string s3) {if (s1.size()+s2.size()!=s3.size()) return false;string1=s1;string2=s2;string3=s3;temp.resize(s1.size()+1,vector<int> (s2.size()+1,0));return func(0,0);}bool func(int l1,int l2){if (l1==string1.size() and l2==string2.size()) return true;if (temp[l1][l2]!=0) return temp[l1][l2]==1;bool result=false;if (l1<string1.size() and string1[l1]==string3[l1+l2])result|=func(l1+1,l2);if (l2<string2.size() and string2[l2]==string3[l1+l2])result|=func(l1,l2+1);temp[l1][l2]=result?1:-1;return result;}
};

375. 猜数字大小II

AC:(题都没有读懂的屑)
temp[l][r]:区间(l,r)的最小花费。

class Solution {
public:vector<vector<int>> temp;int getMoneyAmount(int n) {temp.resize(n+5,vector<int> (n+5,0));return dfs(1,n);}int dfs(int l,int r){if (l>=r) return 0;if (temp[l][r]!=0) return temp[l][r];int result=INT_MAX;for (int i=l;i<=r;i++){int result_temp=max(dfs(l,i-1),dfs(i+1,r))+i;result=min(result,result_temp);}temp[l][r]=result;return result;}
};

403. 青蛙过河

AC:(不看题解也能做啦)
cache[now][next]:从第0个石头开始,走now石头到next石头,是否能够到达终点。

class Solution {
public:vector<int> lb;vector<vector<int>> cache;bool canCross(vector<int>& stones) {if (stones[1]!=1) return false;lb=stones;cache.resize(stones.size(),vector<int> (stones.size(),0));return dfs(0,1);}bool dfs(int now,int next){if (next==lb.size()-1) return true;if (cache[now][next]!=0) return cache[now][next]==1;vector<int> temp;int steps=lb[next]-lb[now];for (int i=next+1;i<lb.size();i++){if (lb[i]==lb[next]+steps-1) temp.push_back(i);if (lb[i]==lb[next]+steps) temp.push_back(i);if (lb[i]==lb[next]+steps+1) temp.push_back(i);if (lb[i]>=lb[next]+steps+2) break;}for (int i=0;i<temp.size();i++)if (dfs(next,temp[i])){cache[next][temp[i]]=1;return true;}else cache[next][temp[i]]=-1;return false;}
};

464. 我能赢吗

超标超标还是超标。
这里共有三个关键:
首先就是思路问题,我有一个错的思路:不论我去选择什么,最终结果我都能赢。这种想法不正确的(例如:输入样例4、6。只要先手去选择1,后手无论怎么选择,先手全部情况能赢。但是按照错误思路,先手如果去选择4,那么先手必然会输。)。也就是说选手只会选择成功最佳方案。
WA:

class Solution {
public:int num1,num2;unordered_set<int> jh;bool canIWin(int maxChoosableInteger, int desiredTotal) {if ((1+maxChoosableInteger)*maxChoosableInteger/2<desiredTotal) return false;num1=maxChoosableInteger;num2=desiredTotal;for (int i=1;i<=maxChoosableInteger;i++) jh.insert(i);return dfs(0,0);}bool dfs(int times,int scores){int iter=0,length=jh.size();int * lb=new int [length];for (auto zz=jh.begin();zz!=jh.end();zz++){lb[iter]=*zz;iter+=1;}for (int i=0;i<length;i++){if (scores+lb[i]>=num2){if (times%2==0) continue;delete [] lb;return false;}jh.erase(lb[i]);if (!dfs(times+1,scores+lb[i])) {delete [] lb;return false;}jh.insert(lb[i]);}delete [] lb;return true;}
};

所以正确思路应是:我的对手十分强大,我选择数必须保证,对手必须全部输掉,否则那么不选这数,继续进行下次循环,循环结束如没找到,那么我就不能够赢。
TLE:

class Solution {
public:int num1,num2;unordered_set<int> jh;bool canIWin(int maxChoosableInteger, int desiredTotal) {if ((1+maxChoosableInteger)*maxChoosableInteger/2<desiredTotal) return false;num1=maxChoosableInteger;num2=desiredTotal;for (int i=1;i<=maxChoosableInteger;i++) jh.insert(i);return dfs(0,0);}bool dfs(int times,int scores){int iter=0,length=jh.size();int * lb=new int [length];for (auto zz=jh.begin();zz!=jh.end();zz++){lb[iter]=*zz;iter+=1;}for (int i=0;i<length;i++){jh.erase(lb[i]);if (scores+lb[i]>=num2) {jh.insert(lb[i]);delete [] lb;return true;}if (!dfs(times+1,scores+lb[i])) {jh.insert(lb[i]);delete [] lb;return true;}jh.insert(lb[i]);}delete [] lb;return false;}
};

暴力我们写出来了,我们该写记忆搜索。但是我们发现由于使用集合并不好写,所以第二关键就是,必须换种存储方式。
TLE:

class Solution {
public:int num1,num2,x=1;bool canIWin(int maxChoosableInteger, int desiredTotal) {if ((1+maxChoosableInteger)*maxChoosableInteger/2<desiredTotal) return false;num1=maxChoosableInteger;num2=desiredTotal;x=(x<<maxChoosableInteger)-1;return dfs(0,0);}bool dfs(int times,int scores){for (int i=1;i<=num1;i++){if (((1<<(i-1))&x)==0) continue;x-=(1<<(i-1));if (scores+i>=num2) {x+=(1<<(i-1));return true;}if (!dfs(times+1,scores+i)) {x+=(1<<(i-1));return true;}x+=(1<<(i-1));}return false;}
};

第三关键记忆搜索
AC:

class Solution {
public:int num1,num2,x=1;vector<int> lb;bool canIWin(int maxChoosableInteger, int desiredTotal) {if ((1+maxChoosableInteger)*maxChoosableInteger/2<desiredTotal) return false;num1=maxChoosableInteger;num2=desiredTotal;x=(x<<maxChoosableInteger)-1;lb.resize(1<<maxChoosableInteger,0);return dfs(0,0);}bool dfs(int times,int scores){if (lb[x]!=0) return lb[x]==1;for (int i=1;i<=num1;i++){if (((1<<(i-1))&x)==0) continue;x-=(1<<(i-1));if (scores+i>=num2) {x+=(1<<(i-1));lb[x]=1;return true;}if (!dfs(times+1,scores+i)) {x+=(1<<(i-1));lb[x]=1;return true;}x+=(1<<(i-1));}lb[x]=-1;return false;}
};

494. 目标和

直接暴力
AC:

class Solution {
public:int num,result=0;vector<int> lb;int findTargetSumWays(vector<int>& nums, int target) {num=target;lb=nums;dfs(0,0);return result;}void dfs(int begin,int count){if (begin==lb.size()){if (count==num) result+=1;return;}dfs(begin+1,count+lb[begin]);dfs(begin+1,count-lb[begin]);}
};

552. 学生出勤记录II

首先暴力
TLE:

class Solution {
public:int mod=1e9+7;int checkRecord(int n) {return dfs(n,0,0)%mod;}int dfs(int n,int A,int P){if (n==0) return 1;int count=0;if (A==0) count=(count+dfs(n-1,1,0))%mod;if (P<=1) count=(count+dfs(n-1,A,P+1))%mod;count=(count+dfs(n-1,A,0))%mod;return count;}
};

记忆搜索
AC:

class Solution {
public:vector<vector<vector<int>>> lb;int mod=1e9+7;int checkRecord(int n) {lb.resize(n,vector<vector<int>> (2,vector<int> (3,0)));return dfs(n,0,0)%mod;}int dfs(int n,int A,int P){if (n==0) return 1;if (lb[n-1][A][P]!=0) return lb[n-1][A][P];int count=0;if (A==0) count=(count+dfs(n-1,1,0))%mod;if (P<=1) count=(count+dfs(n-1,A,P+1))%mod;count=(count+dfs(n-1,A,0))%mod;lb[n-1][A][P]=count;return count;}
};

576. 出借的路径数

首先暴力
TLE:

class Solution {
public:int length,width,mod=1e9+7;int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {length=m,width=n;int count=0;for (int i=1;i<=maxMove;i++)count=(count+dfs(i,startRow,startColumn))%mod;return count;}int dfs(int times,int x,int y){if (times==0){if (x==-1 or x==length or y==-1 or y==width) return 1;return 0;}if (x==-1 or x==length or y==-1 or y==width) return 0;int count=0;if (x>=0) count=(count+dfs(times-1,x-1,y))%mod;if (x<length) count=(count+dfs(times-1,x+1,y))%mod;if (y>=0) count=(count+dfs(times-1,x,y-1))%mod;if (y<width) count=(count+dfs(times-1,x,y+1))%mod;return count;}
};

记忆搜索
wc超时了,怎么办,怎么办,哎呦,你干嘛啊
TLE:

class Solution {
public:int length,width;vector<vector<vector<int>>> lb;int mod=1e9+7;int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {length=m,width=n;lb.resize(maxMove,vector<vector<int>> (m,vector<int> (n,0)));int count=0;for (int i=1;i<=maxMove;i++)count=(count+dfs(i,startRow,startColumn))%mod;return count;}int dfs(int times,int x,int y){if (times==0){if (x==-1 or x==length or y==-1 or y==width) return 1;return 0;}if (x==-1 or x==length or y==-1 or y==width) return 0;if (lb[times-1][x][y]!=0) return lb[times-1][x][y];int count=0;if (x>=0) count=(count+dfs(times-1,x-1,y))%mod;if (x<length) count=(count+dfs(times-1,x+1,y))%mod;if (y>=0) count=(count+dfs(times-1,x,y-1))%mod;if (y<width) count=(count+dfs(times-1,x,y+1))%mod;lb[times-1][x][y]=count;return count;}
};

我寻思这时间复杂度也不高也就 5 0 3 50^3 503
破大防了,C(传)T(统)M(美)D(德)。

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

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

相关文章

C++入坑基础知识点

当学习了C语言之后&#xff0c;很多的小伙伴都想进一步学习C&#xff0c;但两者有相当一部分的内容都是重叠的&#xff0c;不知道该从哪些方面开始入门C&#xff0c;这篇文章罗列了从C到C必学的入门知识&#xff0c;学完就算是踏入C的大门了。 1. 命名空间 写C的时候&#xff…

使用Vue-Grid-Layout实现自定义工作台

前言 当代工作环境要求高度的个性化和定制化&#xff0c;因此&#xff0c;自定义工作台成为了一个热门的需求。Vue-Grid-Layout是一个强大的Vue组件&#xff0c;可以帮助我们实现自定义工作台的功能。在本篇博客中&#xff0c;我将向您介绍如何使用Vue-Grid-Layout来创建一个自…

找不到d3dcompiler_43.dll,无法继续执行代码的原因分析与解决方法

在运行某些软件或游戏时&#xff0c;可能会遇到系统提示找不到 d3dcompiler_43.dll 文件的情况。这个特定的动态链接库文件 (dll) 是 DirectX 3D 编译器组件的一部分&#xff0c;对于许多现代软件游戏的正常运行起着不可或缺的作用。它的主要功能在于将高级着色语言编写的代码转…

零基础学Python之核心基础知识

1.Python入门简介 &#xff08;1&#xff09;什么是Python Life is short, you need Python&#xff01;人生苦短&#xff0c;我用Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言…

MySQL数据库入门(概念+使用)

目录 1. 数据库的概念 1.1 数据库的存储介质 1.2 主流数据库 2. MySQL的基本使用 2.1 链接数据库 2.2 服务器管理 2.3 数据库&#xff0c;服务器和表关系 2.4 简单MySQL语句 3. MySQL架构 4. SQL分类 5. 存储引擎 本篇完。 1. 数据库的概念 数据库是按照数据结构来…

【CSS】页面自适应屏幕宽度(响应式布局媒体查询-@media、弹性布局、网格布局和相对单位-vh/em/%)

【CSS】页面自适应屏幕宽度&#xff08;响应式布局媒体查询-media、弹性布局、网格布局和相对单位-vh/em/%&#xff09; 一、媒体查询&#xff08;media&#xff09;1、媒体类型2、媒体特征3、媒体查询语法4、示例&#xff08;1&#xff09;示例1&#xff08;2&#xff09;示例…

筛选可疑密码

题目描述 情报小组截获了若干个可疑密码&#xff0c;这些密码都是4位数。现在他们获得了一条最新情报&#xff1a;个位数与千位数的和 减去十位数与百位数的和&#xff0c;结果是一个正数。请你帮助情报组筛选目前的可疑密码。 输入 输入两行&#xff0c;第一行是&#xff1…

Codeforces Round 481 (Div. 3)

本场比赛也是没有考察什么算法重点在于思维模式 目录 A. Remove Duplicates B. File Name C. Letters D. Almost Arithmetic Progression E. Bus Video System F. Mentors G. Petyas Exams A. Remove Duplicates 要求我们从右边开始保留数&#xff0c;我们可以考虑的就…

leetcode热题100.二叉树中的最大路径和

Problem: 124. 二叉树中的最大路径和 文章目录 题目解题方法复杂度Code 题目 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 …

c++ 语法函数

函数定义 返回值 函数名(参数列表){ 函数体 return xx } 无返回值 不需要return 返回值类型为 void int sum(int a,int b) {int sum a b;return sum; } int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n"…

pytorch_car_caring 排坑记录

pytorch_car_caring 排坑记录 任务踩坑回顾简单环境问题代码版本问题症状描述解决方法 cuda问题&#xff08;异步问题&#xff09;症状描述解决方法 任务 因为之前那个MPC代码跑出来的效果不理想&#xff0c;看了一天代码&#xff0c;大概看明白了&#xff0c;但要做改进还要有…

C语言指针学习 之 指针是什么

前言 指针是C语言中一个重要概念&#xff0c;也是C语言的一个重要特色&#xff0c;正确而灵活地运用指针可以使程序简洁、紧凑、高效。每一个学习和使用C语言的人都应当深入的学习和掌握指针&#xff0c;也可以说不掌握指针就没有掌握C语言的精华。 一、什么是指针 想弄清楚什…

末世智能毁灭机械

在一个遥远的星球上&#xff0c;AI和机器人在末世中扮演着重要角色。由于一场毁灭性的灾难&#xff0c;人类文明几乎被彻底毁灭&#xff0c;幸存者被迫在废土中艰难求生。为了重建家园&#xff0c;人类和机器人联手&#xff0c;利用智能机械技术开始了重建工作。 然而&#xff…

应用层协议 ——— HTTP协议

应用层协议 ——— HTTP协议 HTTP简介认识URL二、登录信息三、服务器地址四、服务器端口号五、带层次的文件路径六、查询字符串七、片段标识符urlencode和urldecodeHTTP协议格式HTTP请求协议格式HTTP的方法HTTP的状态码HTTP常见的HeaderHTTPS VS HTTP对称加密 VS 非对称加密 HT…

Stable diffusion使用和操作流程

Stable Diffusion是一个文本到图像的潜在扩散模型,由CompVis、Stability AI和LAION的研究人员和工程师创建。它使用来自LAION-5B数据库子集的512x512图像进行训练。使用这个模型,可以生成包括人脸在内的任何图像,因为有开源的预训练模型,所以我们也可以在自己的机器上运行它…

C#基础题

值类型和引用类型之间的区别是什么&#xff1f; 值类型在内存中存储实际值&#xff0c;而引用类型存储对对象的引用。值类型在栈上分配内存&#xff0c;而引用类型在堆上分配内存。值类型是不可变的&#xff0c;而引用类型是可变的。值类型的大小是固定的&#xff0c;而引用类型…

Java工具类库Hutool

这里写目录标题 一、简介二、包含组件三、常用功能演示2、时间工具DateUtil3、数字类工具NumberUtil4、身份认证工具IdcardUtil5、信息脱敏工具DesensitizedUtil6、字段校验工具Validator7、集合工具类CollStreamUtil 一、简介 Hutool是一个小而全的Java工具类库&#xff0c;通…

类与对象

面向对象的程序设计 面对对象的程序 类 类 .... 类 设计程序的过程&#xff0c;就是设计类的过程。 面对对象的程序设计方法&#xff1a; 1.将某类客观事物共同特点&#xff08;属性&#xff09;归纳出来&#xff0c;形成一个数据结构&#xff08;可以用多个变量描述…

elementui 回到顶部报错

<template>Scroll down to see the bottom-right button.<el-backtop target".page-component__scroll .el-scrollbar__wrap"></el-backtop> </template> 使用element的Backtop 回到顶部组件的伙伴们&#xff0c;把官网代码复制到页面使用时…

定义HarmonyOS IDL接口

HarmonyOS IDL简介 HarmonyOS Interface Definition Language&#xff08;简称HarmonyOS IDL&#xff09;是HarmonyOS的接口描述语言。HarmonyOS IDL与其他接口语言类似&#xff0c;通过HarmonyOS IDL定义客户端与服务端均认可的编程接口&#xff0c;可以实现在二者间的跨进程…