# 字符串常规

本文作者:程序员飞云

本站地址:https://www.flycode.icu (opens new window)

转换成小写字母 (opens new window)

验证回文串 (opens new window)

字符串中的第一个唯一字符 (opens new window)

有效的字母异位词 (opens new window)

最长公共前缀 (opens new window)

# 转换成小写字母

给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。

示例 1:

输入:s = "Hello"
输出:"hello"
1
2

示例 2:

输入:s = "here"
输出:"here"
1
2

示例 3:

输入:s = "LOVELY"
输出:"lovely"
1
2

我们需要明确一下ASCII的范围

a-z: 97-122

A-Z: 65-90

0-9: 48-57

题目里面只需要将大写字母转换为小写字母,我们只需要遍历这个字符串判断是否是大写,然后将对应的字符转换为小写就可以。

 public String toLowerCase(String s) {
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<s.length();i++){
            char ch =s.charAt(i);
            if(ch>=65 && ch <=90){
                 ch = (char)(ch+32);
            }
            sb.append(ch);
        }

        return sb.toString();
    }
1
2
3
4
5
6
7
8
9
10
11
12

但是我在这里还发现了官方使用的另一个方式进行转换字符,采用了或运算ch |= 32;

我们以大写字符A 65为例,对应的二进制是 1000001 转换为小写字符a,值是97,二进制是 1100001。

32的二进制是 100000

1000001 | 100000 = 1100001

结果正好是97,所以使用或运算能够帮助我们快速转换字符,而不需要进行强转。

# 验证回文串

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false

示例 1:

输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。
1
2
3

示例 2:

输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。
1
2
3

示例 3:

输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。
由于空字符串正着反着读都一样,所以是回文串。
1
2
3
4

最简单的方式就是先将字符串里面的其他符号都先去除,而且在去除的时候还将大写转换为小写,得到一个只包含小写字母的字符串。然后我们可以使用对撞型双指针从两侧来比较是否是同一个字符。

    public boolean isPalindrome(String s) {
        String res = lowerChar(s);
        int left  = 0;
        int right = res.length()-1;
        while(left<=right){
            if(res.charAt(left) != res.charAt(right)){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    // 大写转为小写,并且去除非字母的字符
    public String lowerChar(String s){
        StringBuilder sb = new StringBuilder();
        int left = 0;
        while(left < s.length()){
            // 不是字母
              // 不是字母或数字
            while (left < s.length() && !Character.isLetterOrDigit(s.charAt(left))) {
                left++;
            }
              // 检查 left 是否超出字符串索引范围
            if (left >= s.length()) {
                break;
            }
            char ch =  s.charAt(left);
            // 判断大小写
            if(ch >= 65 && ch <= 90){
                ch |= 32;
            }
            sb.append(ch);
            left++;
        }
        return sb.toString();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

合并

    public boolean isPalindrome(String s) {
        StringBuilder sb = new StringBuilder();
        int len= s.length();
        // 只保留小写字母
        for(int i=0;i<len;i++){
            char ch = s.charAt(i);
            if(Character.isLetterOrDigit(ch)){
                sb.append(Character.toLowerCase(ch));
            }
        }

        // 判断新的字符串回文
        int slen = sb.length();
        int left  = 0;
        int right = slen-1;
        while(left < right){
            if(sb.charAt(left) != sb.charAt(right)){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 字符串中的第一个唯一字符

给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1

示例 1:

输入: s = "leetcode"
输出: 0
1
2

示例 2:

输入: s = "loveleetcode"
输出: 2
1
2

主要思路就是先使用一个map来存储这些字母出现的次数,然后再遍历一次字符串,找到第一个字符对应的次数为1的字符,直接返回。

    public int firstUniqChar(String s) {
        HashMap<Character,Integer> map = new HashMap<>();
        // 统计次数
        for(int i=0;i<s.length();i++){
            char ch = s.charAt(i);
            map.put(ch,map.getOrDefault(ch,0)+1);
        }

        // 遍历字符串,找到第一个只出现一次的值
        for(int i=0;i<s.length();i++){
            if(map.get(s.charAt(i))==1){
                return i;
            }
        }
        return -1;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 有效的字母异位词

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

**注意:**若 *s**t* 中每个字符出现的次数都相同,则称 *s**t* 互为字母异位词。

示例 1:

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

示例 2:

输入: s = "rat", t = "car"
输出: false
1
2

# 数组排序比较

将字符串转换为数组后,然后将数组重新排序,再比较。

   public boolean isAnagram(String s, String t) {
        char [] s1 = s.toCharArray();
        char [] s2 = t.toCharArray();
        Arrays.sort(s1);
        Arrays.sort(s2);

        if(s1.length != s2.length){
            return false;
        }

        return Arrays.equals(s1,s2);
    }
1
2
3
4
5
6
7
8
9
10
11
12

# 使用map

我们可以使用一个hashmap存储字符串s里面的所有字符以及对应字符出现的个数,然后在遍历字符串t,如果t里面的字符出现了,那么map里面对应的元素的值就要减少,直到为0,如果出现了map存储的元素的值是小于0,意味着肯定不满足条件。

    public boolean isAnagram(String s, String t) {
        if(s.length()!=t.length()){
            return false;
        }
`       // 將字符串s的里面字符和对应的出现的次数添加到map里面
        HashMap<Character,Integer> map = new HashMap<>();
        for(int i=0;i<s.length();i++){
            char ch = s.charAt(i);
            map.put(ch,map.getOrDefault(ch,0)+1);
        }

        // 遍历字符串t里面的所有字符,如果出现了和字符串s里面对应的元素,那么次数就减1
        for(int i=0;i<t.length();i++){
            char ch = t.charAt(i);
            map.put(ch,map.getOrDefault(ch,0)-1);
            if(map.get(ch) < 0 ){
                return false;
            }
        }
        return true;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例 1:

输入:strs = ["flower","flow","flight"]
输出:"fl"
1
2

示例 2:

输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
1
2
3

# 纵向扫描

最简单的方式就是将第一个字符串作为模板,其他的字符串都和第一个进行比较,如果对应的字符串字符和第一个字符串的对应的元素不同,那么直接将第一个字符串进行截取。

例如"flower","flow","flight"

flower为模板

flowflower比较,到w的时候停止比较,将flower截取成flow

flowflight比较 ,第三个元素是oi,不同,所有停止比较,直接截取fl返回

纵向扫描时,从前往后遍历所有字符串的每一列,比较相同列上的字符是否相同,如果相同则继续对下一列进行比较,如果不相同则当前列不再属于公共前缀,当前列之前的部分为最长公共前缀。

    public String longestCommonPrefix(String[] strs) {
        if(strs.length<1 || strs == null){
            return "";
        }
        // 第一个字符串的长度
        int len = strs[0].length();
        // 数组字符串的个数
        int count = strs.length;
        // 遍历第一个字符串,获取对应的字符
        for(int i=0;i<len;i++){
            char c = strs[0].charAt(i);

            // 遍历数组,将数组里面对应的字符比较
            for(int j=1;j<count;j++){

                // 如果当前的第一个字符串的长度等于后续遍历数组字符串的长度,或者字符串对应的字符不是字符串1里面的字符,则返回
                if(i==strs[j].length() || strs[j].charAt(i)!=c){
                    return strs[0].substring(0,i);
                }
            }
        }
        return strs[0];
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 横向匹配

我们可以将每一个字符串从数组里面拿出来两两匹配找到最小前缀,然后将这个前缀继续和后续的字符串比较。

  public String longestCommonPrefix(String[] strs) {
        if(strs.length<1 || strs == null){
            return "";
        }
        // 第一个字符串
       String prefix = strs[0];
       int count = strs.length;
      // 遍历字符串数组,匹配前缀
       for(int i = 1;i<count;i++){
           prefix = longestCommonPrefix(prefix,strs[i]);
           if(prefix.length()==0){
               break;
           }
       }

       return prefix;
    }

    // 获取两个字符串的最小公共前缀
    public String longestCommonPrefix(String str1,String str2){
        int minLen = Math.min(str1.length(),str2.length());
        int index = 0;
        // 获取最小前缀的下标位置
        while(index<minLen && str1.charAt(index) == str2.charAt(index)){
            index++;
        }
        return str1.substring(0,index);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
最近更新: 12/30/2024, 12:04:33 AM
飞云编程   |