《七月集训》第二日——字符串

前言

这是七月集训的第2日,今日的训练内容是 字符串

解题报告

1.力扣2315

原题链接

2315. 统计星号

题目概述

给你一个字符串 s ,每 两个 连续竖线 ‘|’ 为 一对 。换言之,第一个和第二个 ‘|’ 为一对,第三个和第四个 ‘|’ 为一对,以此类推。

请你返回 不在 竖线对之间,s 中 ‘*’ 的数目。

注意,每个竖线 ‘|’ 都会 恰好 属于一个对。

解题思路

用一个栈记录一下 ‘|’ 的数量就可以了。

源码剖析

int countAsterisks(char * s){
    int len = strlen(s);
    int stack = 0;
    int ans = 0;
    int i;
    for(i = 0;i<len;++i){
        if(s[i]=='|'&&stack==0){
            stack++;
            continue;
        }
        if(s[i]=='|'&&stack!=0){
            stack--;
            continue; 
        }
        if(stack==0&&s[i]=='*'){
            ans++;
        }
    }
    return ans;
}

2.力扣459

原题链接

459. 重复的子字符串

题目概述

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

解题思路

这题之前有做过类似的题目,使用了比较暴力的算法进行枚举,这次学习了官解的思路:如果一个字符串是满足条件的子串,那么把这个子串从头去掉,然后再加到字符串的尾部,这个字符串和原来仍然相同。这是主要思路,然后由这个思路通过一系列的证明可以证明:如果把原来的字符串 s 接在本身的后面,然后去除第一个和最后一个字符之后 s 是新字符串的子串,那么就可以得出原来的字符串是满足条件的。

同时这里使用了strtsr(a,b);函数,也作积累,是用于在 a 中找到 b 第一次出现的位置

源码剖析

bool repeatedSubstringPattern(char* s) {
    int n = strlen(s);
    char k[2 * n + 1];
    k[0] = 0;
    strcat(k, s);
    strcat(k, s);
    return strstr(k + 1, s) - k != n;
}

3.力扣1790

原题链接

1790. 仅执行一次字符串交换能否使两个字符串相等

题目概述

给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。

如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false 。

解题思路

一开始把这题想的过于简单了,实际上要满足各种刁钻的不同情况的字符串的话,需要满足两个条件:首先两个字符串中不同的字符的数目不可以超过 2 组,这里使用一个栈就可以了。

接下来是,不同的那些字符串的字母一定要是相同的,这里我使用了两层判断来确认不同部分的字符串是否相等。第一层是先将不一样的字符串塞到哈希表中,所有字母出现的次数都应该是偶数次,接下来,两个字符串不同部分的字符只需要 ascii 码也相同,就必定是一样的了。

源码剖析

bool areAlmostEqual(char * s1, char * s2){
    int hash[26]={0};
    int len = strlen(s1);
    int i;
    int stack = 0;
    int stack1=0,stack2=0;
    for(i=0;i<len;++i){
        if(s1[i]!=s2[i]){
            stack++;
            stack1+=s1[i];
            stack2+=s2[i];
            hash[s1[i]-'a']++;
            hash[s2[i]-'a']++;
            if(stack>2) return false;
        }else{
            continue;
        }
    }
    for(i = 0;i<26;++i){
        if(hash[i]&1)
        return false;
    }
    if(stack1!=stack2) return false;
    return true;
}

4.力扣1961

原题链接

1961. 检查字符串是否为数组前缀

题目概述

给你一个字符串 s 和一个字符串数组 words ,请你判断 s 是否为 words 的 前缀字符串 。

字符串 s 要成为 words 的 前缀字符串 ,需要满足:s 可以由 words 中的前 k(k 为 正数 )个字符串按顺序相连得到,且 k 不超过 words.length 。

如果 s 是 words 的 前缀字符串 ,返回 true ;否则,返回 false 。

解题思路

直接遍历然后注意移动下标就可以了。

源码剖析

bool isPrefixString(char * s, char ** words, int wordsSize){
    int len = strlen(s);
    int i,j=0,k=0;
    for(i=0;i<len;++i){
        if(j>=wordsSize) return false;
        if(s[i]==words[j][k]){
            if(words[j][k+1]==NULL){
                j++;
                k=0;
                continue;
            }else{
                k++;
                continue;
            }
        }else return false;
    }
    if(s[i]!=NULL||k!=0) return false;
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值