【庚】字符串

编程之美 3.1

s1 = AABCD, s2 = CDAA
Return : true

给定两个字符串 s1 和 s2,要求判定 s2 是否能够被 s1 做循环移位得到的字符串包含。

s1 进行循环移位的结果是 s1s1 的子字符串,因此只要判断 s2 是否是 s1s1 的子字符串即可。

2. 字符串循环移位

编程之美 2.17

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

将字符串向右循环移动 k 位。

将 abcd123 中的 abcd 和 123 单独翻转,得到 dcba321,然后对整个字符串进行翻转,得到 123abcd。

3. 字符串中单词的翻转

程序员代码面试指南

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

将每个单词翻转,然后将整个字符串翻转。

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

242. Valid Anagram (Easy)

Leetcode / 力扣

s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.

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

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

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

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

409. Longest Palindrome

Input : "abccccdd"
Output : 7
Explanation : One longest palindrome that can be built is "dccaccd", whose length is 7.

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

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

public int longestPalindrome(String s) {
    int[] cnts = new int[256];
    for (char c : s.toCharArray()) {
        cnts[c]++;
    }
    int palindrome = 0;
    for (int cnt : cnts) {
        palindrome += (cnt / 2) * 2;
    }
    if (palindrome < s.length()) {
        palindrome++;   // 这个条件下 s 中一定有单个未使用的字符存在,可以把这个字符放到回文的最中间
    }
    return palindrome;
}

6. 字符串之间的关系问题

字符串同构

205.字符串同构

Given "egg", "add", return true.
Given "foo", "bar", return false.
Given "paper", "title", return true.

记录一个字符上次出现的位置,如果两个字符串中的字符上次出现的位置一样,那么就属于同构。

//好处: 不需要再循环一次了。

上下两个都需要map,不能使用一个map,除非两个的字符串中的映射都是一致的比如两个的a都映射到c,这样用一个map

public boolean isIsomorphic(String s, String t) {
    int n = s.length();
    int[] mapS = new int[128];
    int[] mapT = new int[128];
    for (int i = 0; i < n; i++) {
        char c1 = s.charAt(i);
        char c2 = t.charAt(i);
        //当前的映射值是否相同
        if (mapS[c1] != mapT[c2]) {
            return false;
        } else {
            //是否已经修改过,修改过就不需要再处理
            if (mapS[c1] == 0) {
                mapS[c1] = i + 1;
                mapT[c2] = i + 1;
            }
        }
    }
    return true;
}

比较一般的方法

public boolean isIsomorphic(String s, String t) {
    return isIsomorphicHelper(s, t) && isIsomorphicHelper(t, s);

}

private boolean isIsomorphicHelper(String s, String t) {
    int n = s.length();
    HashMap<Character, Character> map = new HashMap<>();
    for (int i = 0; i < n; i++) {
        char c1 = s.charAt(i);
        char c2 = t.charAt(i);
        if (map.containsKey(c1)) {
            if (map.get(c1) != c2) {
                return false;
            }
        } else {
            map.put(c1, c2);
        }
    }
    return true;
}

290. 单词规律

public boolean wordPattern(String pattern, String str) {
    HashMap<Character,String> map = new HashMap<>();
    String[] array = str.split(" ");
    if(pattern.length() != array.length){
        return false;
    }
    for(int i = 0; i < pattern.length();i++){
        char key = pattern.charAt(i);
        if(map.containsKey(key)){
            if(!map.get(key).equals(array[i])){
                return false;
            }
        }else{
            //判断 value 中是否存在
            if(map.containsValue(array[i])){
                return false;
            }
            map.put(key, array[i]);
        }
    }
    return true;
}

作者:windliang
链接:https://leetcode-cn.com/problems/word-pattern/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--53/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

7.回文串

131. 分割回文串

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回 s 所有可能的分割方案。

1.最简单的,回文的判断一定要直接拿过来做

2,回溯法,类似于全排列

在这里插入代码片

132. 分割回文串 II

class Solution {
    public int minCut(String s) {
        int[] dp = new int[s.length()];
        dp[0] = 0;
        for(int i = 1; i < s.length(); i++){
            dp[i] = dp[i-1]+1;
            for(int j = 0; j < i; j++){
                if(checkPalindrome(s,j,i)){
                    dp[i] = j > 0 ? Math.min(dp[j-1]+1,dp[i]) : 0;
                }
            }
        }
        return dp[s.length()-1]; 
    }


    private boolean checkPalindrome(String str, int left, int right) {
        // 严格小于即可
        while (left < right) {
            if (str.charAt(left) != str.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }    
}


更简单一点:使用动态规划存储是不是回文

            if (s.charAt(i) == s.charAt(j) && (i - j < 2 || dp[j + 1][i - 1])) {
                dp[j][i] = true;
                min_s[i] = j == 0 ? 0 : Math.min(min_s[i], min_s[j - 1] + 1);
            }
class Solution {
    public int minCut(String s) {
        int n = s.length();
        int[] min_s = new int[n];
        boolean[][] dp = new boolean[n][n];
        for (int i = 0; i < n; i++) {
            min_s[i] = i;
            for (int j = 0; j <= i; j++) {
                if (s.charAt(i) == s.charAt(j) && (i - j < 2 || dp[j + 1][i - 1])) {
                    dp[j][i] = true;
                    min_s[i] = j == 0 ? 0 : Math.min(min_s[i], min_s[j - 1] + 1);
                }
            }
        }
        return min_s[n - 1];
    }
}

作者:powcai
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii/solution/zi-ding-xiang-xia-he-zi-di-xiang-shang-by-powcai-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

7.0 回文子字符串个数

647. Palindromic Substrings (Medium)

//主要思想,遍历一遍 以每个字符串为核心

Leetcode / 力扣

Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

从字符串的某一位开始,尝试着去扩展子字符串。

private int cnt = 0;

public int countSubstrings(String s) {
    for (int i = 0; i < s.length(); i++) {
        extendSubstrings(s, i, i);     // 奇数长度
        extendSubstrings(s, i, i + 1); // 偶数长度
    }
    return cnt;
}

private void extendSubstrings(String s, int start, int end) {
    while (start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)) {
        start--;
        end++;
        cnt++;
    }
}

//我的不简洁
class Solution {
    int res = 0;
    public int countSubstrings(String s) {
        for(int i = 0; i < s.length(); i++){
            helper(s, i);
        }
         return res;
    }
    private void helper(String s, int ind) {
        int start = ind;
        int end = ind;
        //回文的个数是奇数
        while(start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)){
            res++;
            start--;
            end++;
        }
        //个数是偶数
        if(ind > 0){
            start = ind - 1;
            end = ind;
            while(start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)){
                res++;
                start--;
                end++;        
            }    
        }
    }
}


7.1分割回文串

131. 分割回文串

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回 s 所有可能的分割方案。

回溯法:类似与全排列的情况。在最后一步添加

class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> res = new ArrayList<>();
        backtrack(res, s,  new ArrayList<String>());
        return res;

    }

    private void backtrack(List<List<String>> res, String s, ArrayList<String> tmp) {
        if (s == null || s.length() == 0) res.add(new ArrayList<>(tmp));
        for (int i = 1; i <= s.length(); i++) {
            if (isPalidrome(s.substring(0, i))) {
                // System.out.println(s.substring(0, i));
                tmp.add(s.substring(0, i));
                backtrack(res, s.substring(i, s.length()), tmp);
                tmp.remove(tmp.size() - 1);
            }
        }
    }

    private  boolean isPalidrome(String sb) {
        int left = 0;
        int right = sb.length() - 1;
        while (left < right) {
            if (sb.charAt(left) != sb.charAt(right)) return false;
            left++;
            right--;
        }
        return true;

    }
}

作者:powcai
链接:https://leetcode-cn.com/problems/palindrome-partitioning/solution/dong-tai-gui-hua-dfs-by-powcai/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

7.2 最长回文子串

5. 最长回文子串

中心扩散法 巧妙,奇数个偶数个的情况都考虑了

public String longestPalindrome(String s) {
    if (s == null || s.length() < 1) return "";
    int start = 0, end = 0;
    for (int i = 0; i < s.length(); i++) {
        int len1 = expandAroundCenter(s, i, i);
        int len2 = expandAroundCenter(s, i, i + 1);
        int len = Math.max(len1, len2);
        if (len > end - start) {
            start = i - (len - 1) / 2;
            end = i + len / 2;
        }
    }
    return s.substring(start, end + 1);
}

private int expandAroundCenter(String s, int left, int right) {
    int L = left, R = right;
    while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
        L--;
        R++;
    }
    return R - L - 1;
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

动态规划 这个好,边界不用考虑

public class Solution {

    public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }

        boolean[][] dp = new boolean[len][len];

        // 初始化
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        int maxLen = 1;
        int start = 0;

        for (int j = 1; j < len; j++) {
            for (int i = 0; i < j; i++) {

                if (s.charAt(i) == s.charAt(j)) {
                    if (j - i < 3) {
                        dp[i][j] = true;
                    } else {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                } else {
                    dp[i][j] = false;
                }

                // 只要 dp[i][j] == true 成立,就表示子串 s[i, j] 是回文,此时记录回文长度和起始位置
                if (dp[i][j]) {
                    int curLen = j - i + 1;
                    if (curLen > maxLen) {
                        maxLen = curLen;
                        start = i;
                    }
                }
            }
        }
        return s.substring(start, start + maxLen);
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

9. Palindrome Number (Easy)

Leetcode / 力扣

要求不能使用额外空间,也就不能将整数转换为字符串进行判断。

将整数分成左右两部分,右边那部分需要转置,然后判断这两部分是否相等。

public boolean isPalindrome(int x) {
    if (x == 0) {
        return true;
    }
    if (x < 0 || x % 10 == 0) {
        return false;
    }
    int right = 0;
    //x是右半部分的数构建的
    while (x > right) {
        right = right * 10 + x % 10;
        x /= 10;
    }
    //如果是奇数,只需要除以10即可
    return x == right || x == right / 10;
}

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

696. Count Binary Substrings (Easy)

Leetcode / 力扣

Input: "00110011"
Output: 6
Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".

//1 将字符串分为不同的groups
//每个groups都
//使用preLen记录前一个group,思想很好
public int countBinarySubstrings(String s) {
    int preLen = 0, curLen = 1, count = 0;
    for (int i = 1; i < s.length(); i++) {
        if (s.charAt(i) == s.charAt(i - 1)) {
            curLen++;
        } else {
            preLen = curLen;
            curLen = 1;
        }

        if (preLen >= curLen) {
            count++;
        }
    }
    return count;
}

//我的思路, 和上一道题类似,轮询下,以i和i-1为枢轴,如果满足条件就扩大/
class Solution {
    int res = 0;
    public int countBinarySubstrings(String s) {
        for(int i = 1; i < s.length(); i++){
            helper(s, i - 1, i);
        }
        return res;
      
    }
    private void helper(String s, int b, int e){
        if(s.charAt(b)==s.charAt(e)) return;
        res++;
        while(b > 0 && e < s.length() - 1 && s.charAt(b-1)==s.charAt(b) && s.charAt(e)==s.charAt(e+1)){
            res++;
            b--;
            e++;
        }
    }
}

原来可以叫做中心扩展法

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];
            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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

10.不同的子序列

115. 不同的子序列

给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数。

一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE""ABCDE" 的一个子序列,而 "AEC" 不是)

题目数据保证答案符合 32 位带符号整数范围。

子串问题

重复的DNA序列

187. 重复的DNA序列

class Solution {
    List<String> ans = new ArrayList<>() ;
    HashSet<String> set = new HashSet<>() ;
    public List<String> findRepeatedDnaSequences(String s) {
        if(s == null) return ans ;
        int len = s.length() ;
        if(len <= 10) return ans ;
        for(int i = 0 ; i + 10 <= len ; i++){
            String temp = s.substring(i,i+10) ;
            if(set.add(temp)){
               continue ; 
            }else if(!ans.contains(temp)){
                ans.add(temp) ;
            }
        }
        return ans ;
    }
}

我的:使用lambda去重

class Solution {
    public List<String> findRepeatedDnaSequences(String s) {
        //暴力:每隔十个放到map中
        List<String> res = new ArrayList<>();
        Set<String> map = new HashSet<>();
        for (int i = 0; i < s.length(); i++) {            
            if(i+10 <= s.length()){
                String temp = s.substring(i,i+10);
                if(map.contains(temp)) {
                    res.add(temp);
                    continue;
                }
                map.add(temp);
            }else{
                break;
            }
        }
        return res.stream().distinct().collect(Collectors.toList());
    }
}

匹配问题

验证IP地址

469. 验证IP地址

  • 根据分割后长度的不同,分成两种情况考虑
  • 每种情况仔细考虑不同的情况
class Solution {
    public String validIPAddress(String IP) {
        String[] IP4Arr = IP.split("\\.",-1);
        if(IP4Arr.length == 4){
            return isIP4Arr(IP4Arr);
        }

        String[] IP6Arr = IP.split(":",-1);
        if(IP6Arr.length == 8){
            return isIP6Arr(IP6Arr);
        }

        return "Neither";
    }

    public String isIP4Arr(String[] IP4Arr){
        for(String ip : IP4Arr){
            if(ip.length() > 3 || ip.length() <= 0){
                return "Neither";
            }
            for(int i = 0 ;i < ip.length();++i){
                if(!Character.isDigit(ip.charAt(i))){
                    return "Neither";
                }
            }
            int num = Integer.parseInt(ip);
            if(num > 255 || String.valueOf(num).length() != ip.length()){
                return "Neither";
            }
        }
        return "IPv4";
    }

     public String isIP6Arr(String[] IP6Arr){
        for(String ip : IP6Arr){
            if(ip.length() > 4 || ip.length() <= 0){
                return "Neither";
            }
            for(int i = 0 ;i < ip.length();++i){
                char c = ip.charAt(i);
                if(!Character.isDigit(c) && !( 'a' <= c && c <= 'f') && !('A' <= c && c <= 'F')){
                    return "Neither";
                }
            }
        }
        return "IPv6";
    }
}

作者:souljoy
链接:https://leetcode-cn.com/problems/validate-ip-address/solution/zhi-xing-yong-shi-1-ms-zai-suo-you-java-ti-jia-203/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

动态字符串

Z 字形变换

6. Z 字形变换

class Solution {
public:
    string convert(string s, int numRows) {

        if (numRows == 1) return s;

        vector<string> rows(min(numRows, int(s.size())));
        int curRow = 0;
        bool goingDown = false;

        for (char c : s) {
            rows[curRow] += c;
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }

        string ret;
        for (string row : rows) ret += row;
        return ret;
    }
};

作者:LeetCode
链接:https://leetcode-cn.com/problems/zigzag-conversion/solution/z-zi-xing-bian-huan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值