电信保温杯笔记——代码随想录 刷题攻略 字符串

电信保温杯笔记——代码随想录 刷题攻略

代码随想录 刷题攻略
电信保温杯笔记——代码随想录 刷题攻略

1.字符串:这道题目,使用库函数一行代码搞定

讲义地址

344.反转字符串

leetcode地址

class Solution {
    public void reverseString(char[] s) {
        if(s == null || s.length < 2) return;
        int left = 0;
        int right = s.length -1;
        while (left < right){
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
    }
}

在这里插入图片描述

2.字符串:简单的反转还不够!

讲义地址

541. 反转字符串II

leetcode地址

class Solution {
    public String reverseStr(String s, int k) {
        char[] temp = s.toCharArray();
        int len = s.length();
        int loop = len / (2*k);
        int residue = len % (2*k);
        for (int i = 0; i < loop; i++) {
            reverseString(temp, i*2*k, i*2*k+k-1);
        }
        if (residue < k){
            reverseString(temp, loop*2*k, len-1);
        }else {
            reverseString(temp, loop*2*k, loop*2*k+k-1);
        }
        return new String(temp);
    }

    public void reverseString(char[] s, int left, int right) {
        if(s == null || right-left < 1) return;
        while (left < right){
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
    }
}

在这里插入图片描述

3.字符串:替换空格

讲义地址

剑指Offer 05.替换空格

leetcode地址

class Solution {
    public String replaceSpace(String s) {
        StringBuilder res = new StringBuilder();
        for(Character c : s.toCharArray())
        {
            if(c == ' ') res.append("%20");
            else res.append(c);
        }
        return res.toString();
    }
}

在这里插入图片描述
使用StringBuilder效率比String高

4.字符串:花式反转还不够!

讲义地址

151.翻转字符串里的单词

leetcode地址

class Solution {
    /**
     * 不使用Java内置方法实现
     * <p>
     * 1.去除首尾以及中间多余空格
     * 2.反转整个字符串
     * 3.反转各个单词
     */
    public String reverseWords(String s) {
        // System.out.println("ReverseWords.reverseWords2() called with: s = [" + s + "]");
        // 1.去除首尾以及中间多余空格,并反转整个字符串
        StringBuilder sb = removeSpace(s);
        // 2.反转各个单词
        reverseEachWord(sb);
        return sb.toString();
    }

    private StringBuilder removeSpace(String s) {
        // System.out.println("ReverseWords.removeSpace() called with: s = [" + s + "]");
        int start = 0;
        int end = s.length() - 1;
        while (s.charAt(start) == ' ') start++;
        while (s.charAt(end) == ' ') end--;
        StringBuilder sb = new StringBuilder();
        // 倒序收集,即反转整个字符串
        while (start <= end) {
            char c = s.charAt(end);
            
            if (c != ' ' || 
                    // 上一个收集的字符不为空格
                    sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }
            end--;
        }
        // System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]");
        return sb;
    }

    /**
     * 反转字符串指定区间[start, end]的字符
     */
    public void reverseString(StringBuilder sb, int start, int end) {
        // System.out.println("ReverseWords.reverseString() called with: sb = [" + sb + "], start = [" + start + "], end = [" + end + "]");
        while (start < end) {
            char temp = sb.charAt(start);
            sb.setCharAt(start, sb.charAt(end));
            sb.setCharAt(end, temp);
            start++;
            end--;
        }
        // System.out.println("ReverseWords.reverseString returned: sb = [" + sb + "]");
    }

    private void reverseEachWord(StringBuilder sb) {
        int start = 0;
        int end = 1;
        int n = sb.length();
        while (start < n) {
            while (end < n && sb.charAt(end) != ' ') {
                end++;
            }
            reverseString(sb, start, end - 1);
            start = end + 1;
            end = start + 1;
        }
    }
}

在这里插入图片描述

小结

翻转字符串的核心代码就是题目344的代码。

5.字符串:反转个字符串还有这个用处?

讲义地址

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

leetcode地址

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder sb = new StringBuilder();
        for (int i = n; i < s.length(); i++) {
            sb.append(s.charAt(i));
        }
        for (int i = 0; i < n; i++) {
            sb.append(s.charAt(i));
        }
        return sb.toString();
    }
}

在这里插入图片描述

6.帮你把KMP算法学个通透

讲义地址

28. 实现 strStr()

leetcode地址

方式1:暴力实现

class Solution {
    public int strStr(String haystack, String needle) {
//        if (needle == "") return 0; 不能这样写,
//        因为String类指向堆空间,堆空间再指向方法区中
//        的字符串,这样写会地址不一样而出错
        if (needle.length() == 0) return 0;
        int len_h = haystack.length();
        int len_n = needle.length();
        if (len_h < len_n) return -1;
        int left = 0;
        int right = 0;
        while (left < len_h){
            for (int i = 0; i < len_n; i++) {
                if (haystack.charAt(right) != needle.charAt(i)){
                    break;
                }
                // needle遍历了一次,找到时长度刚好等于needle的长度
                if (right - left + 1 == len_n){
                    return left;
                }
                right++;
            }
            left++;
            right = left;
            // 剩余长度达不到needle的长度
            if (len_h - len_n < right){
                break;
            }
        }
        return -1;
    }
}

在这里插入图片描述

方式2:KMP

class Solution {
    //前缀表(不减一)Java实现
    public int strStr(String haystack, String needle) {
        if (needle.length() == 0) return 0;
        int[] next = new int[needle.length()];
        getNext(next, needle);

        int j = 0;
        for (int i = 0; i < haystack.length(); i++) {
            while (j > 0 && needle.charAt(j) != haystack.charAt(i)) 
                j = next[j - 1];
            if (needle.charAt(j) == haystack.charAt(i)) 
                j++;
            if (j == needle.length()) 
                return i - needle.length() + 1;
        }
        return -1;

    }
    
    private void getNext(int[] next, String s) {
        int j = 0;// j:前缀尾部 and 前缀的长度
        next[0] = 0;
        for (int i = 1; i < s.length(); i++) {
        	// i:后缀尾部
            while (j > 0 && s.charAt(j) != s.charAt(i)) 
                j = next[j - 1];
            if (s.charAt(j) == s.charAt(i)) 
                j++;
            next[i] = j; 
        }
    }
}

在这里插入图片描述

小结

getNext函数中,j = next[j - 1] 难以理解,j 回退到下一次比较的起始位置。

7.字符串:KMP算法还能干这个!

讲义地址

459.重复的子字符串

leetcode地址

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int len = s.length();
        if (len == 0 || len == 1) {
            return false;
        }

        int[] next = new int[len];
        getNext(next, s);
        if (next[len -1] != 0 && len % (len - next[len -1]) == 0){
            return true;
        }
        
        return false;
    }
    public void getNext(int[] next, String s){
        int j = 0;
        next[0] = 0;
        for (int i = 1; i < s.length(); i++) {
            while (j>0 && s.charAt(j) != s.charAt(i)){
                j = next[j-1];
            }
            if (s.charAt(j) == s.charAt(i)){
                j++;
            }
            next[i] = j;
        }
    }
}

在这里插入图片描述
对于"abcabcabcabc",它的next数组为:
在这里插入图片描述

字符串:总结篇!

讲义地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值