LeetCode字符串专题

------------恢复内容开始------------

String 方法

下面是 String 类支持的方法,更多详细,参看 Java String API 文档:

 

SN(序号)方法描述
1 char charAt(int index)
返回指定索引处的 char 值。
2 int compareTo(Object o)
把这个字符串和另一个对象比较。返回的是ascii码中差值
3 int compareTo(String anotherString)
按字典顺序比较两个字符串。
4 int compareToIgnoreCase(String str)
按字典顺序比较两个字符串,不考虑大小写。
5 String concat(String str)
将指定字符串连接到此字符串的结尾。
6 boolean contentEquals(StringBuffer sb)
当且仅当字符串与指定的StringBuffer有相同顺序的字符时候返回真。
7 static String copyValueOf(char[] data)
返回指定数组中表示该字符序列的 String。
8 static String copyValueOf(char[] data, int offset, int count)
返回指定数组中表示该字符序列的 String。
9 boolean endsWith(String suffix)
测试此字符串是否以指定的后缀结束。
10 boolean equals(Object anObject)
将此字符串与指定的对象比较。
11 boolean equalsIgnoreCase(String anotherString)
将此 String 与另一个 String 比较,不考虑大小写。
12 byte[] getBytes()
 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
13 byte[] getBytes(String charsetName)
使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
14 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
字符从此字符串复制到目标字符数组。
15 int hashCode()
返回此字符串的哈希码。
16 int indexOf(int ch)
返回指定字符在此字符串中第一次出现处的索引。
17 int indexOf(int ch, int fromIndex)
返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索
18 int indexOf(String str)
 返回指定子字符串在此字符串中第一次出现处的索引。
19 int indexOf(String str, int fromIndex)
返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
20 String intern()
 返回字符串对象的规范化表示形式。
21 int lastIndexOf(int ch)
 返回指定字符在此字符串中最后一次出现处的索引
22 int lastIndexOf(int ch, int fromIndex)
返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索
23 int lastIndexOf(String str)
返回指定子字符串在此字符串中最右边出现处的索引
24 int lastIndexOf(String str, int fromIndex)
 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
25 int length()
返回此字符串的长度。
26 boolean matches(String regex)
告知此字符串是否匹配给定的正则表达式。
27 boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
28 boolean regionMatches(int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
29 String replace(char oldChar, char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的
30 String replaceAll(String regex, String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
31 String replaceFirst(String regex, String replacement)
 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
32 String[] split(String regex)
根据给定正则表达式的匹配拆分此字符串。
33 String[] split(String regex, int limit)
根据匹配给定的正则表达式来拆分此字符串。
34 boolean startsWith(String prefix)
测试此字符串是否以指定的前缀开始。
35 boolean startsWith(String prefix, int toffset)
测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
36 CharSequence subSequence(int beginIndex, int endIndex)
 返回一个新的字符序列,它是此序列的一个子序列
37 String substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串
38 String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。
39 char[] toCharArray()
将此字符串转换为一个新的字符数组。
40 String toLowerCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
41 String toLowerCase(Locale locale)
 使用给定 Locale 的规则将此 String 中的所有字符都转换为小写。
42 String toString()
 返回此对象本身(它已经是一个字符串!)。
43 String toUpperCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
44 String toUpperCase(Locale locale)
使用给定 Locale 的规则将此 String 中的所有字符都转换为大写。
45 String trim()
返回字符串的副本,忽略前导空白和尾部空白。
46 static String valueOf(primitive data type x)
返回给定data type类型x参数的字符串表示形式。

------------恢复内容结束------------

1.编程之美 3.1

2.编程之美 2.17

3.程序员代码面试指南

没有书。。。

4. 两个字符串包含的字符是否完全相同

242. Valid Anagram (Easy)

Leetcode / 力扣

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

答案:

可以用 HashMap 来映射字符与出现次数,然后比较两个字符串出现的字符数量是否相同。

由于本题的字符串只包含 26 个小写字符,因此可以使用长度为 26 的整型数组对字符串出现的字符进行统计,不再使用 HashMap。

用到了上面的39号方法

public boolean isAnagram(String s, String t) {
    int[] cnts = new int[26];//26个0
    for (char c : s.toCharArray()) {
        cnts[c - 'a']++;//比如a-a=0,c-a=2这是对应索引...所以cnts里面是int数组 其实是字母们的索引对应的26个0
这一步意思是对应26个索引值对应的0++中。。。就是出现1次就是,出现2次就是2.没出现就还是0
}
for (char c : t.toCharArray()) { cnts[c - 'a']--;//同上,统计字母的出现次数 但是这个是把前面++过的次数降下来 若t和s相等 则还是26个0 } for (int cnt : cnts) { if (cnt != 0) { return false; } } return true; }

5. 计算一组字符集合可以组成的回文字符串的最大长度

409. Longest Palindrome (Easy)

Leetcode / 力扣

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。

在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

答案:

使用长度为 256 的整型数组来统计每个字符出现的个数,每个字符有偶数个可以用来构成回文字符串

因为回文字符串最中间的那个字符可以单独出现,所以如果有单独的字符就把它放到最中间

public int longestPalindrome(String s) {
    int[] cnts = new int[256];//这次直接把ascii码的256个char的索引搬过来
    for (char c : s.toCharArray()) {
        cnts[c]++;//这里放的也是对应索引的次数,只是这个索引不像上面考虑从0开始了,在ascii码中索引是几这里就是几,然后还是存的该索引对应的字符出现次数
    }
    int palindrome = 0;
    for (int cnt : cnts) {
        palindrome += (cnt / 2) * 2;//这个得出的是可以组成的最大长度。如果该字符有偶数个,则正好可以构成,若有奇数个,则需要减去1个多余的
    }
    if (palindrome < s.length()) {//发生了减去了多余的话,允许加上1个放中间
        palindrome++;   // 这个条件下 s 中一定有单个未使用的字符存在,可以把这个字符放到回文的最中间
    }
    return palindrome;
}

完全没想到的妙啊。。。看题目完全不会做觉得怎么会是简单题。。。原来只要是次数为偶数就可以,如果有奇数则/2*2就去掉多余的那个了。若发生了去掉,不管发生几次,加1放中间就行。

6. 字符串同构

205. Isomorphic Strings (Easy)

给定两个字符串 s 和 t,判断它们是否是同构的。

如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。

所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

Leetcode / 力扣

我的想法是两个计次数的256长度的数组排序以后看是否相等。。感觉会超时。。而且该方法次数顺序好像保证不了。。。不排序,剔除=0的即拿出不为0的,这样呢?

答案是在两个分别计数的同时就可以判断!!因为对应于字符串的索引i在0到lengrh内s的i索引对应元素出现次数要等于t的i索引对应元素的出现次数

public boolean isIsomorphic(String s, String t) {
    int[] preIndexOfS = new int[256];
    int[] preIndexOfT = new int[256];
    for (int i = 0; i < s.length(); i++) {
        char sc = s.charAt(i), tc = t.charAt(i);//从字符串们中对应位置取的char,可以分别做各自次数数组中的索引!!!!!!!
        if (preIndexOfS[sc] != preIndexOfT[tc]) {
            return false;
        }
        preIndexOfS[sc] = i + 1;//这是换了一种遍历字符串的方法,前面是变成数组遍历,这里使用charAt(index)方法取char遍历。
                      因为我们要用到i索引保证sc和tc是字符串同一索引处取出的字符! preIndexOfT[tc] = i + 1;//也不是从0开始计次数了,而是s的索引值加1,
                    有重复的char自动替换最新的,重点是对比sc和tc两个索引对应的元素即次数是否相等。 }
return true; }

震惊1!数组中还可以用char类型做索引!因为与int一一对应吧可能,比如a就是97

7. 回文子字符串个数

647. Palindromic Substrings (Medium)

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。

Leetcode / 力扣

emmm我真的是不会做字符串的题。。感觉要用128题hashset那个跳来做。。

答案都好难理解。。。

class Solution {
    int counts = 0;
    public int countSubstrings(String s) {
        for(int i=0;i<s.length();i++){
            //奇数个数的回文子串,以自身为两边扩展子串保证还是奇数
            extendSubstrings(s,i,i);
            //偶数个数的回文子串,以两个相邻的索引向两边扩展保证子串还是偶数
            extendSubstrings(s,i,i+1);
        }
        return counts;
    }

    private void extendSubstrings(String s,int start,int end){//对于一个字符串s,指定两个初始位置,判断两个位置的字母是否相同,
                      //然后逐渐向两边扩展,每次扩展都记录counts数,直到不满足要求为止(有一边到头了或者两边字母不一样了)
while(start>=0 && end<s.length() && s.charAt(start)==s.charAt(end)){ //往两边扩展字符串 start--; end++; //回文子串计数加一 counts++; } } }

评论区都在cue第5题

5. 最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

class Solution {
    public String longestPalindrome(String s) {
         int len = s.length();
        if (len < 2) {
            return s;
        }
        int maxLen = 1;
        String res = s.substring(0, 1);

    for (int i = 0; i < s.length(); i++) {  以s的索引遍历
        String oddStr=extendSubstrings(s, i, i);     // 奇数长度
        String evenStr=extendSubstrings(s, i, i + 1); // 偶数长度
        String maxLenStr = oddStr.length() > evenStr.length() ? oddStr : evenStr;//选长的
            if (maxLenStr.length() > maxLen) {
                maxLen = maxLenStr.length();
               res = maxLenStr;//存住每次最长的那个
            }
    }
    return res;
}

private String extendSubstrings(String s, int start, int end) {
    while (start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)) {
        start--;
        end++;
    }
   // 这里要小心,跳出 while 循环时,恰好满足 s.charAt(i) != s.charAt(j),因此不能取 i,不能取 j
        return s.substring(start + 1, end);//返回一个该start和end下往两边扩展的最长的子序列!!
}
}

评论区这两题还用动态规划做。。。不会。。。看不懂。。。

8. 判断一个整数是否是回文数

9. Palindrome Number (Easy)

Leetcode / 力扣

我的想法上一题加equals方法,但是这里输入的是个int,需要int转String.

int类型转String类型的三种方法:

1.String str = Integer.toString(num); (最快)

2.String str = String.valueOf(num); (一般)

3.String str = num + ""; (最慢)

class Solution {
    public boolean isPalindrome(int x) {
        String s = Integer.toString(x);
        if(s.length()==1){
            return true;
        }
       int len = s.length();
        if(len%2==0){
            return extendSubstrings(s,len/2-1,len/2);
        }else{
            return extendSubstrings(s,len/2,len/2); 
        }

    }
    private boolean extendSubstrings(String s,int start,int end){
        while(start>=0 && end<s.length() && s.charAt(start)==s.charAt(end)){
            //往两边扩展字符串
            start--;
            end++;
        }
        if(s.equals(s.substring(start+1, end))){
            return true;
        }
        return false;
    }
}

9. 统计二进制字符串中连续 1 和连续 0 数量相同的子字符串个数

696. Count Binary Substrings (Easy)

给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。

重复出现的子串要计算它们出现的次数。

示例 1 :

输入: "00110011"
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。

请注意,一些重复出现的子串要计算它们出现的次数。

另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。

Leetcode / 力扣

emmmm???不会。。。

两种解法

1.中心扩展(类似回文子串的判断)

看完题目给的示例,如果将0与1看成对应,那么符合题目要求的子串就关于其中心(中间两个元素的中间)成轴对称就如同回文字符串关于中心轴对称。不过有一点不同,就是在本问题中对称中心只能是两个字符的中间,而回文字符串的中心可以是某一个字母
所以这个题也可以类似于统计回文字符串的数目那样,用中心扩展的方法。本问题中对称中心只能是两个字符的中间,可以用整形序列[1, s.length() - 1]来表示回文中心的位置,那么left = i - 1, right = i 就是最中心的两个字符
  比如i = 1时left = 0, right = 1 ,就是第一个可能的满足题目要求的子串。由原字符串中第一,第二个字符构成。
  所以遍历每一个回文中心的循环为for(int i = 1; i < s.length(); i++)
在循环中首先要保证,回文中心左右的两个字符char leftChar = chars[left], rightChar = chars[right];一个是0,另外一个是1
  如果都是1或者都是0,那么没有以这个为中心的符合要求的字串,后续就不用从中心向外扩展了if(leftChar == rightChar) continue;。
  如果leftChar != rightChar,就以此为中心,使用一个while循环来计数这个中心有多少个符合题意的子串。循环条件首先保证索引不越界,其次leftChar左边的字符都要和它相等,rightChar右边的字符都要和它相等。不断向外扩展就是left--; right++
时间复杂度为O(n+k),其中k为符合条件的子串的数目。空间复杂度为O(1)。

public int countBinarySubstrings(String s) {
        int result = 0;
        char[] chars = s.toCharArray();
        for(int i = 1; i < s.length(); i++){
            int left = i - 1, right = i;//直接在遍历里面写之前放到另一个方法里的取子序列操作,因为这里不分奇偶,一定是偶
            char leftChar = chars[left], rightChar = chars[right];//之前直接是s.charAt(left)。啊啊啊这里只能是这样!!原因见下面!!
            if(leftChar == rightChar)
                continue;
            while(left >= 0 && right < s.length() && chars[left] == leftChar && chars[right] == rightChar){
                              //因为这里他需要这样判断,左边的都一样,右边的也得都一样。而不是之前的相等或者不相等 left
--; right++; result++
; } } return result; } 作者:ustcyyw 链接:https://leetcode-cn.com/problems/count-binary-substrings/solution/696java-zhong-xin-kuo-zhan-yu-hui-wen-chuan-xiang-/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

就得这样写,不能和之前那个start,end那样判断扩展相等。

我怕明天就会忘了。。。。

 

posted @ 2020-06-08 21:04  xinxinpang  阅读(253)  评论(0编辑  收藏  举报