【leetcode】字符串

380 阅读5分钟

【leetcode】字符串

String常用方法

int length() - 返回字符串长度

举个意想不到的例子:String s = "😓", s.length() = ?。

char charAt(int) - 返回字符串中指定索引的字符,索引从0开始

boolean equals(Object) - 判断是否与指定字符串相等

boolean equalsIgnoreCase(String) - 同上,忽略大小写

boolean contentEquals(StringBuffer) - 判断是否与指定StringBuffer相等

int compareTo(String) - 与指定字符串比较,返回Unicode编码的差值,相等时为0

int compareToIgnoreCase(String) - 同上,忽略大小写

boolean startsWith(String, int) - 该串从指定偏移开始,是否以指定字符串为前缀

例如:String s = "abcd", s.startsWith("cd", 2)为true。

boolean startsWith(String) - 是否以指定字符串为前缀

boolean endsWith(String) - 是否以指定字符串为后缀

int indexOf(int) - 返回字符首次出现的索引

int lastIndexOf(int) - 返回字符的最后出现的索引

String substring(int) - 返回当前串从指定位置开始的子串,包括指定位置

s.substring(0) == s为true

String substring(int, int) - 返回当前串从指定位置开始和结束的字串

s.substring(0, s.length()) == s为true, 左闭右开区间[start, end)

String concat(String) - 在当前串后面添加指定串

String replace(char, char) - 将串中的所有指定字符替换为另一个指定字符

String replace(CharSequence, CharSequence) - 将当前串中所有的指定字符序列替换为另一个字符序列

String replaceAll(String, String) - 将当前串中所有的指定字符串替换为另一个字符串

String replaceFirst(String, String) - 将当前串中的首次出现的指定字符串替换为另一个字符串

boolean matches(String) - 判断当前串是否满足给定的正则表达式

boolean contains(CharSequence) - 判断当前串是否包含指定字符序列

String[] split(String) - 以给定正则表达式将当前串分割并返回字符串数组

"axbyc".split("[xy]"), 结果为[a, b, c]

String[] split(String, int) - 以给定正则表达式将当前串分割为指定个字符串,0表示不限制个数

"axbyc".split("[xy]", 2), 结果为[a, byc]

static String join(CharSequence, CharSequence...) - 将给定的字符序列数组用给定的字符序列连接起来,并返回结果

String.join("-", "abc", "def", "xyz"), 结果为"abc-def-xyz"

static String join(CharSequence, Iterable) - 同上,字符序列数组可以换为可迭代类型如List/Set等

String toLowerCase() - 将当前字符串转为全小写

String toUpperCase() - 将当前字符串转为全大写

String trim() - 去掉当前串首尾的空白符

char[] toCharArray() - 将当前字符串转为字符数组,该字符数组是字符串内部的字符数组的一个拷贝

String s = "abc"; char[] arr = s.toCharArray(); arr[0] = 'x'; 修改字符数组不影响原来的字符串

static String copyValueOf(char[]) - 将字符数组转为字符串

static String copyValueOf(char[], int, int) - 将字符串数组从指定偏移开始的指定长度转为字符串

static String valueOf(int/char/char[]/long/float/double/boolean) - 将基本类型值转为字符串

double d = 0.3f; String.valueOf(d); 结果为0.30000001192092896

最长公共前缀

题目 取第一个字符串,从其前缀[0,1)开始到整串,判断其它串是否以此为前缀。

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        }
        if (strs.length == 1) {
            return strs[0];
        }
        
        for (int j = 1; j < strs[0].length() + 1; j++) { // 遍历第一个字符串的前缀
            for (int i = 1; i < strs.length; i++) { // 遍历每个字符串
                if (!strs[i].startsWith(strs[0].substring(0, j))) { // 判断每个串是否以[0, j)为前缀
                    return j == 1 ? "" : strs[0].substring(0, j - 1);
                }
            }
        }
        return strs[0];
    }
}

最长回文子串

题目 中心扩散法。遍历字符串,判断每个位置上的最长回文子串。

class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() == 0) {
            return "";
        }
        char[] arr = s.toCharArray();
        int start = 0, end = 0; // [start, end]
        for (int i = 0; i < s.length() - 1; i++) {
            int l1 = longestPalindrome(arr, i, i); // ABA型,奇数
            int l2 = longestPalindrome(arr, i, i + 1); // AA型,偶数
            int l = Math.max(l1, l2);
            if (l > end - start + 1) { // 更新最大值
                start = i - (l - 1) / 2;
                end = i + l / 2;
            }
        }
        return s.substring(start, end + 1);
    }
    
    // 返回最长回文子串的长度
    public int longestPalindrome(char[] arr, int left, int right) {
        while (left >= 0 && right < arr.length && arr[left] == arr[right]) {
            left--;
            right++;
        }
        return right - left - 1;
    }
}

翻转字符串里的单词

题目

  1. api,先分割为数组,数组反转,再组合为字符串。
class Solution {
    public String reverseWords(String s) {
        if (s == null || s.isEmpty()) {
            return "";
        }
        String[] arr = s.trim().split("\\s+");
        int left = 0, right = arr.length - 1;
        while (left < right) {
            String temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
        return String.join(" ", arr);
    }
}
  1. toCharArray之后原地操作。第一步trim;第二步去掉单词之间的多余空格;第三步翻转整个数组;第四步翻转每个单词。
class Solution {
    public String reverseWords(String s) {
        if (s == null || s.isEmpty()) {
            return "";
        }
        
        char[] arr = s.toCharArray();
        int length = trim(arr);
        if (length < 1) {
            return "";
        }
        length = removeRedundantBlank(arr, length);
        reverseArray(arr, 0, length - 1);
        reverseWord(arr, length);
        return String.valueOf(arr, 0, length);
    }
    
    // 去掉数组两边的空格
    public int trim(char[] arr) {
        int preBlank = 0;
        for (int i = 0; i < arr.length && arr[i] == ' '; i++) {
            preBlank++;
        }
        int postBlank = 0;
        for (int i = arr.length - 1; i >= 0 && arr[i] == ' '; i--) {
            postBlank++;
        }
        for (int i = 0; i < arr.length - postBlank && i + preBlank < arr.length; i++) {
            arr[i] = arr[i + preBlank];
        }
        return arr.length - preBlank - postBlank;
    }
    
    // 去除单词之间多余的空格
    public int removeRedundantBlank(char[] arr, int length) {
        int i = 1;
        while (i < length) {
            int count = 0;
            while (i < length && arr[i - 1] == ' ' && arr[i] == ' ') {
                count++;
                i++;
            }
            if (count > 0) {
                int j = i;
                while (j < length) {
                    arr[j - count] = arr[j];
                    arr[j] = ' ';
                    j++;
                }
                length -= count;
                i--;
            }
            i++;
        }
        return length;
    }
    
    // 翻转字符数组
    public void reverseArray(char[] arr, int left, int right) {
        while (left < right) {
            char temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
    }
    
    // 翻转单词 eulb -> blue
    public void reverseWord(char[] arr, int length) {
        int i = 0;
        while (i < length) {
            int start = i;
            int end = i - 1;
            while (i < length && arr[i] != ' ') {
                end++;
                i++;
            }
            reverseArray(arr, start, end);
            i++;
        }
    }
}

字符串匹配算法:KMP算法

class Solution {
    public int strStr(String haystack, String needle) {
        if (haystack == null || needle == null || haystack.length() < needle.length() ) {
            return -1;
        }
        if (needle.length() == 0) {
            return 0;
        }
        return kmp(haystack, needle);
    }
    
    public int kmp(String txt, String pat) {
        char[] patArr = pat.toCharArray();
        int[] next = getNext(patArr);
        int i = 0;
        int j = 0;
        while (i < txt.length() && j < pat.length()) {
            if (txt.charAt(i) == patArr[j]) {
                i++;
                j++;
            } else if (next[j] == -1) {
                i++;
            } else {
                j = next[j];
            }
        }
        return j == patArr.length ? i - j : -1;
    }
    
    public int[] getNext(char[] pat) {
        if (pat.length == 1) {
            return new int[]{-1};
        }
        int[] next = new int[pat.length];
        next[0] = -1;
        next[1] = 0;
        int pos = 2;
        int cn = 0;
        while (pos < next.length) {
            if (pat[pos - 1] == pat[cn]) {
                next[pos++] = ++cn;
            } else if (cn > 0) {
                cn = next[cn];
            } else {
                next[pos++] = 0;
            }
        }
        return next;
    }
}