第五天打卡——字符串

字符串

344.反转字符串

很常规的一道题


541. 反转字符串II (总是会出现细节上的漏洞,导致测试用例不通过

上一题的升级版

思路破解点在于,字符串每隔k个就要翻转k个数值,关键在于找到每次的翻转区间[i,i+k-1]。

稍微注意一下,字符数组转成的字符串的方法。String s = new String(char);


剑指Offer 05.替换空格

常规题目(没有用双指针


151.翻转字符串里的单词

分三步走。

1、去除多余空格

使用双指针判断前后以及中间多余空格:

        a. while循环去除头部和尾部空格

        b. 循环遍历字符串去除中间空格

        (while中加continue很容易变成死循环,需要在continue之前加上 start++的条件)

2、将整个字符串全部翻转

3、把每个单词翻转

突破点在于循环找到每个单词的start和end。

总结:注意s.equals();的使用

//s.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型 
if (" ".equals(String.valueOf(s.charAt(i)))){}

剑指Offer58-II.左旋转字符串

思路突破点:

翻转函数直接调用上一题的,修改以下翻转区间即可。


28. 实现 strStr()

无语了,因为用了“==”没有用equals.(),报错调试了半小时。真服了,无语死了!

思路关键点:

1、两个字符串的循环比较

2、getNext():获取next数组的函数编写

第一个问题:循环比较

指针i不回退,直接for循环遍历文本串。

j指针有多个分支情况:( j 指针下标从1开始)

        a. j >=1 且 j != i 的时候,一直循环j = next[j-1]。直到 j=0,或者 j == i 两个指针值相等时跳出循环

        b. j == i。表示两个指针值相等时跳出循环

                b.1. 指针j遍历到了最后一位,输出 i - 模式串的长度+1

                b.2. 两个指针值相等,但没有到最后一位,j++。继续后一位的比较

        c. j = 0。表示一直没有相等的值,j回退到了第一位。此时,令j =1;i+1。

第二个问题:获取next[]数组

// 1<k<j   max{k|(p1……pk-1) == (pj-k+1……pj-1)} 下标从1开始
// others  k=1

// j=1     k=0   
// j=2     k=1   next数组前两位固定是0和1

459.重复的子字符串

两种方式:1、移动匹配        2、KMP

移动匹配:

给定字符串s="a, b, c, a, b, c"。令s+s拼接在一起,去除第一个和最后一个字符。

如果剩余的字符串中有是s,则说明s是由重复字符串构成的。

int indexOf(String str) :返回第一次出现的指定子字符串在此字符串中的索引。 
int indexOf(String str, int startIndex):从指定的索引处开始,返回第一次出现的指定子字符串在此字符串中的索引。 
int lastIndexOf(String str) :返回在此字符串中最右边出现的指定子字符串的索引。 
int lastIndexOf(String str, int startIndex) :从指定的索引处开始向后搜索,返回在此字符串中最后一次出现的指定子字符串的索引。

图二

KMP算法

最长公共前后缀。

字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。

在字符串中,只要最长公共前后缀的长度 > = 字符串长度/2。   

字符串长度减去最长公共前后缀长度剩下的部分可以被字符串整除

就是最小重复子串。

如下图:字符串s的最长公共前后缀的长度:6(由next[]数组的最后一位获得)

最小重复子串长度:s.length() - 6

图三

KMP算法超出时间限制?why? 

//KMP算法
    public static boolean repeatedSubstringPattern(String s) {
        //获取最长公共前缀数组,与next[]数组有些微的不一样
        int[] next = new int[s.length()];
        if (s.length() >= 1){
            next[0] = 0;
        }
     
        for (int j = 1; j < s.length(); j++){
            int maxSize = 0;
            for (int k = 1; k <= j; k++){
                String str1 = s.substring(0,k);
                String str2 = s.substring(j-k+1,j+1);

                if (str1.equals(str2) && maxSize < k){
                    maxSize = k;
                }
            }
            next[j] = maxSize;
        }

        int sub = s.length() - next[s.length()-1];
        if (sub < s.length() && s.length()%sub == 0){
            return true;
        }

        return false;
    }

双指针回顾 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值