今天的两题
P205
题目:
第一眼我看题目,想到的是他们的格式应该是一样的,如:egg和add都是122型的。
所以用哈希表,遍历的获取映射规则,如果经过映射后可以从s到t,就可以说明可以。
需要注意的是,如果只是单一的映射,不满足条件,如egg和adr
a-e,d-g,r-g.这样说明他是对的,但结果明显不是,因此我们需要满足一一映射的关系,使用2次哈希表即可。
for***遍历
获取规则
先看有无规则
有规则
对应可以--继续
对应不可以--返回false
无规则--创建规则
建立对应
如何看有无规则???
哈希表
因此我看了看哈希表在c++的使用,博客地址如下
https://blog.csdn.net/luolaihua2018/article/details/109412566
简单来说主要分为2类哈希表,map有序,unordered_map无序。本题中无序的即可。
重点的是 count这个函数。
其主要作用是返回表里有无这个元素,有返回1,无返回0.
因此最终代码如下:
class Solution {
public:
bool isIsomorphic(string s, string t) {
unordered_map<char ,char> ss;
unordered_map<char ,char> tt;
//创建哈希表
if(s.size()!=t.size()){
return false;
}
if(s==""&&t==""){
return true;
}
int len=s.size();
//排除数组为空和表大小不相等的情况
for(int i=0;i<len;i++){
char x=s[i];
char y=t[i];
//检测有无规则
if(ss.count(x)!=0&&tt.count(y)==0||ss.count(x)==0&&tt.count(y)!=0){
return false;//映射对应不上
}
if(ss.count(x)!=0&&tt.count(y)!=0){
//检测规则是否可以
if(ss[x]!=y||tt[y]!=x){
return false;
}
}
else{//没有规则,创建规则
ss[x]=y;
tt[y]=x;
}
}
return true;
}
};
P392
题目:
分析,s的i+1元素检验的条件是s的i元素已经通过了检验,检测范围为s的i检测后的范围到最后
s[i+1]检测--->
s[i]已经在t[j]处检验到
所以s[i+1]的检测范围是(j,t.size());
第一次想的是双指针,慢指针指向长度较小的S,快指针指向的是较长的t,很容易得到代码如下:
class Solution {
public:
bool isSubsequence(string s, string t) {
if(s==""){
return true;
}
long long len=t.length();
long long leslen=s.length();
long long slow=0;
long long fast=0;
for(fast=0;fast<len;fast++){
if(t[fast]==s[slow]){
slow++;
if(slow==leslen){
return true;
}
}
}
return false;
}
};
但是很明显,这对扩充题没有用。因此还有别的做法?我看了题解,知道了另外2个做法。
第二种,动态规划
主要思路是从后往前建立一个矩阵,通过动态规划减小检测的次数,代码如下
class Solution {
public:
bool isSubsequence(string s, string t) {
int len1=s.size();
int len2=t.size();
vector< vector <int> > dp(len2+1,vector<int>(26,0));
for(int i=0;i<26;i++){
dp[len2][i]=len2;
}
//赋予初值
//遍历
for(int i=len2-1;i>=0;i--){
for(int j=0;j<26;j++){
if(t[i]==j+'a'){
dp[i][j]=i;
}//表示出现
else{
dp[i][j]=dp[i+1][j];
}
}
}
//找字串
int add=0;
for(int i=0;i<len1;i++){
if(dp[add][s[i]-'a']==len2){
return false;//表示没有这个字符
}
add=dp[add][s[i]-'a']+1;//更新下一个开始的文位置
}
return true;
}
};
第三种方法,折半查找:
class Solution {
public:
bool isSubsequence(string s, string t) {
const int n = t.size();
vector<vector<int>> dp(26);
for(int i = 0; i < n; ++i) //预处理
dp[t[i] - 'a'].push_back(i); //字符->下标
int tmp = -1;
for(auto c: s){ //二分找出每一个大于当前下标的位置
auto it = upper_bound(dp[c - 'a'].begin(), dp[c - 'a'].end(), tmp);
if(it == dp[c - 'a'].end()) return false; //如果无法满足递增
tmp = *it;
}
return true;
}
};