• 【数据结构与算法】字符串经典题


    翻转移位相关方法

    右移

    s = "abcd123" k = 3
    Return "123abcd"
    

    先分别将“abcd”和“123”翻转,再将整个字符串翻转,即可得到结果。

    单词翻转

    s = "I am a student"
    Return "student a am I"
    

    先分别将每个单词翻转,最后将整个句子进行翻转即得到结果

    有效的字母异位词

    LeetCode:有效的字母异位词

    题目描述:

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

    示例:

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

    思想:

    1.使用26位计数器
    因为本题仅限于小写英文字母,所以使用26位数组来进行标记即可
    2.map.getOrDefault(ch, 0)
    若不存在则返回0。使用这个函数可稍微优化代码,不会太臃肿。
    3.遍历String的优化写法

    //方法一
    for(int i=0;i<s.length();++i){
          char c = s.charAt(i);
    }
    //方法二
    for(char ch : s.toCharArray()){
    }
    

    方法二比方法一性能好不少

    代码:

    我自己的蠢方法,使用hashmap但是特别不优雅

    class Solution {
        public boolean isAnagram(String s, String t) {
            HashMap<Character,Integer> map = new HashMap<>();
            Integer v;
            for(int i=0;i<s.length();++i){
                char c = s.charAt(i);
                if((v = map.get(c))!=null){
                    map.put(c,v+1);
                }else{
                    map.put(c,1);
                }
            }
            for(int i=0;i<t.length();++i){
                char c = t.charAt(i);
                if((v = map.get(c))!=null){
                    if(v==1) 
                        map.remove(c);
                    else
                        map.put(c,v-1);
                }else{
                    return false;
                }
            }
            return map.isEmpty();
        }
    }
    

    更加优化的hashmap写法:

    public boolean isAnagram_2(String s, String t) {
        Map<Character, Integer> map = new HashMap<>();
        for (char ch : s.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }
        for (char ch : t.toCharArray()) {
            Integer count = map.get(ch);
            if (count == null) {
                return false;
            } else if (count > 1) {
                map.put(ch, count - 1);
            } else {
                map.remove(ch);
            }
        }
        return map.isEmpty();
    }
    

    本题的标准做法:

    class Solution {
        public boolean isAnagram(String s, String t) {
            int[] arr = new int[26];
            for(char c:s.toCharArray()){
                arr[c-'a'] +=1;
            }
            for(char c:t.toCharArray()){
                arr[c-'a'] -=1;
            }
            for(int item : arr){
                if(item!=0) return false;
            }
            return true;
        }
    }
    

    最长回文串

    LeetCode:最长回文串

    题目描述:

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

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

    注意:
    假设字符串的长度不会超过 1010。

    示例:

    输入:
    "abccccdd"
    
    输出:
    7
    
    解释:
    我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
    

    思想:

    这题主要切入点容易想到:先用数组存储每个字母的出现次数。然后判断这个数组,仅满足多个偶数+一个奇数,才能组成回文数。

    注意:

    • 存在大写字母,范围应该是65-122;
    • 最后判断是否存在奇数,可以用如下方法判断
    if(res < s.length()) res++;
    

    这样很巧妙。我一开始做法是在循环内部判断,那样会徒增复杂性

    代码:

    class Solution {
        public int longestPalindrome(String s) {
            int[] arr = new int[58];
            for(char c : s.toCharArray()){
                arr[c - 'A']++;
            }
            int res=0;
            //boolean b=false;
            for(int k : arr){
                //if(k%2 == 1) b = true;
                res += (k/2)*2;
            }
            if(res < s.length()) res++;
            return res;
        }
    }
    

    同构字符串

    /五星/
    LeetCode:同构字符串

    题目描述:

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

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

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

    示例:

    输入: s = "paper", t = "title"
    输出: true
    

    思想:

    这题我根本没想到切入点。看了答案才明白。
    遍历到某个元素时,上一次出现该元素的位置,如果不相等就不同构,相等则继续遍历
    想到这一点就好做了

    代码:

    class Solution {
        public boolean isIsomorphic(String s, String t) {
            int[] arr_s = new int[128];
            int[] arr_t = new int[128];
            for(int i=0;i<s.length();++i){
                char ch1=s.charAt(i),ch2=t.charAt(i);
                if(arr_s[ch1]!=arr_t[ch2]){
                    return false;
                }
                arr_s[ch1]=arr_t[ch2]=i+1;
            }
            return true;
        }
    }
    

    回文子串

    LeetCode:回文子串

    题目描述:

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

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

    示例:

    输入: "aaa"
    输出: 6
    说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".
    

    思想:

    • 回文串中心位置进行扩展,累计可以扩展的次数,遍历完所有中心位置之后,即得到结果;
    • 回文串有两种,奇数串和偶数串。可以通过low和high来控制;

    代码:

    class Solution {
        public int countSubstrings(String s) {
            int res = 0;
            char[] arr = s.toCharArray();
            for(int i=0;i<s.length();++i){
                res +=expandCount(arr,i,i);
                res +=expandCount(arr,i,i+1);
            }
            return res;
        }
        private int expandCount(char[] arr, int low, int high){
            int count = 0 ;
            while(low>-1&&high<arr.length){
                if(arr[low]!=arr[high])
                    break;
                ++count;
                --low;
                ++high;
    
            }
            return count;
        }
    }
    
  • 相关阅读:
    基于jdk8+selenium3+chrome86的UI自动化测试
    服务器虚拟化管理解决方案PVM发送c+a+d组合键
    web端测试技巧记录
    redis-基本数据类型及应用场景
    idea编译时报GC overhead limit exceeded
    cmd常用命令
    @property和@属性.setter的用法
    游陶然亭记
    山城
    记京都春节
  • 原文地址:https://www.cnblogs.com/buptleida/p/12991090.html
Copyright © 2020-2023  润新知