力扣Day2

今天的两题

P205

P392

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;
    }
};

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值