4、字符串

代码随想录
LeetCode 题解
字符串匹配 Rabin-Karp 算法
字符串匹配 KMP 算法

1、反转字符串

344 - 反转字符串

public void reverseString(char[] s) {
    int p1 = 0;
    int p2 = s.length - 1;

    char temp;
    while (p1 < p2) {
        temp = s[p1];
        s[p1] = s[p2];
        s[p2] = temp;
        p1++;
        p2--;
    }
}

2、反转字符串 II

541 - 反转字符串 II

public String reverseStr(String s, int k) {
    int n = s.length();
    char[] arr = s.toCharArray();

    // arr[i ... i + 2k - 1]
    for (int i = 0; i < n; i += 2 * k) {
        reverse(arr, i, Math.min(n - 1, i + k - 1));
    }

    return new String(arr);
}

/**
 * 反转 arr[p1 ... p2]
 */
public void reverse(char[] arr, int p1, int p2) {
    char temp;
    while (p1 < p2) {
        temp = arr[p1];
        arr[p1] = arr[p2];
        arr[p2] = temp;
        p1++;
        p2--;
    }
}
public String reverseStr(String s, int k) {
    char[] arr = s.toCharArray();
    reverseStr(arr, 0, k);
    return new String(arr);
}

/**
 * 反转 arr[l ... n - 1] 的前 k 个字符
 */
private void reverseStr(char[] arr, int l, int k) {
    if (l >= arr.length - 1) return;

    // 反转 arr[l ... l + k - 1]
    int p1 = l;
    int p2 = Math.min(arr.length - 1, l + k - 1);

    char temp;
    while (p1 < p2) {
        temp = arr[p1];
        arr[p1] = arr[p2];
        arr[p2] = temp;
        p1++;
        p2--;
    }

    reverseStr(arr, l + 2 * k, k);
}

3、替换空格

剑指 Offer 05 - 替换空格

public String replaceSpace(String s) {
    StringBuilder sb = new StringBuilder();
    for (char c : s.toCharArray()) {
        if (c == '.') sb.append(' ');
        else sb.append(c);
    }
    return sb.toString();
}

4、反转字符串中的单词

151 - 反转字符串中的单词

public String reverseWords(String s) {
    String[] arr = s.trim().split(" ");
    StringBuilder sb = new StringBuilder();

    for (int i = arr.length - 1; i >= 0; i--) {
        String word = arr[i];

        if (word.equals("")) continue;

        sb.append(word);
        if (i != 0) sb.append(" ");
    }

    return sb.toString();
}

5、左旋转字符串

剑指 Offer 58 - II - 左旋转字符串

public String reverseLeftWords(String s, int n) {
    return s.substring(n) + s.substring(0, n);
}

6、找出字符串中第一个匹配项的下标

28 - 找出字符串中第一个匹配项的下标

public int strStr(String s, String t) {
    if (t.length() == 0) return 0;
    if (s.length() < t.length()) return -1;

    int[] lps = getLPS(t);

    int si = 0; // sIndex
    int ti = 0; // tIndex
    while (si < s.length()) {
        if (s.charAt(si) == t.charAt(ti)) {
            si++;
            ti++;
            if (ti == t.length()) return si - t.length();
        }
        else if (ti > 0) ti = lps[ti - 1];
        else si++;
    }

    return -1;
}

private int[] getLPS(String t) {
    // lps[i] = length(t[0 ... i] max border)
    int[] lps = new int[t.length()];

    for (int i = 1; i < lps.length; i++) {
        int a = lps[i - 1];
        while (a > 0 && t.charAt(a) != t.charAt(i)) a = lps[a - 1];
        if (t.charAt(a) == t.charAt(i)) lps[i] = a + 1;
    }

    return lps;
}

7、重复的子字符串

459 - 重复的子字符串

如果字符串 str 可以由它的一个子串重复多次构成
str = s + s
str + str = [s + s] + [s + s] = s + [s + s] + s

如果字符串 str 不可以由它的一个子串重复多次构成
str = s1 + s2
str + str = [s1 + s2] + [s1 + s2] = s1 + [s2 + s1] + s2 != s1 + [s1 + s2] + s2
public boolean repeatedSubstringPattern(String s) {
    String str = s + s;
    return str.substring(1, str.length() - 1).contains(s);
}
public boolean repeatedSubstringPattern(String s) {
    int n = s.length();
    int[] lps = getLPS(s);

    return lps[n - 1] != 0 && n % (n - lps[n - 1]) == 0;
}

private int[] getLPS(String t) {
    // lps[i] = length(t[0 ... i] max border)
    int[] lps = new int[t.length()];

    for (int i = 1; i < lps.length; i++) {
        int a = lps[i - 1];
        while (a > 0 && t.charAt(a) != t.charAt(i)) a = lps[a - 1];
        if (t.charAt(a) == t.charAt(i)) lps[i] = a + 1;
    }

    return lps;
}
posted @ 2023-05-29 15:40  lidongdongdong~  阅读(3)  评论(0编辑  收藏  举报