力扣刷题系列——字符串相关

字符串相关算法题

1.有效的字母异位词

力扣242:https://leetcode-cn.com/problems/valid-anagram/description/

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

示例 1:

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

示例 2:

  • 输入: s = "rat", t = "car"
  • 输出: 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;
}

2.最长回文串

力扣409:https://leetcode-cn.com/problems/longest-palindrome/description/

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

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

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

示例 1:

  • 输入:"abccccdd"
  • 输出:7

解释:我们可以构造的最长的回文串是"dccaccd", 它的长度是 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;
}

3.同构字符串

力扣205:https://leetcode-cn.com/problems/isomorphic-strings/description/

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

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

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

示例 1:

  • 输入: s = "egg", t = "add"
  • 输出: true

示例 2:

  • 输入: s = "foo", t = "bar"
  • 输出: false

示例 3:

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

说明:你可以假设 s 和 t 具有相同的长度。

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

代码实现:

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);
        if (preIndexOfS[sc] != preIndexOfT[tc]) {
            return false;
        }
        preIndexOfS[sc] = i + 1;
        preIndexOfT[tc] = i + 1;
    }
    return true;
}

4.回文子串

力扣647:https://leetcode-cn.com/problems/palindromic-substrings/

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

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

示例 1:

  • 输入:"abc"
  • 输出:3

解释:三个回文子串: "a", "b", "c"
示例 2:

  • 输入:"aaa"
  • 输出:6

解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

代码实现:

//https://leetcode-cn.com/problems/palindromic-substrings/solution/liang-dao-hui-wen-zi-chuan-de-jie-fa-xiang-jie-zho/
class Solution {
    public int countSubstrings(String s) {
        if(s==null) return 0;
        int count = 0;
        int len = s.length();
        boolean[][] dp = new boolean[len][len];
        for(int j=0;j<len;j++){
            for(int i=0;i<=j;i++){
                if(s.charAt(i)==s.charAt(j) && (j-i<2 || dp[i+1][j-1])){
                    dp[i][j] = true;
                    count++;
                }
            }
        }
        return count;
    }
}


//解二
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++;
    }
}

5.回文数

力扣9:https://leetcode-cn.com/problems/palindrome-number/description/

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 1:

  • 输入: 121
  • 输出: true

示例 2:

  • 输入: -121
  • 输出: false

解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:

  • 输入: 10
  • 输出: false

解释: 从右向左读, 为 01 。因此它不是一个回文数。

代码实现:

class Solution {
    public boolean isPalindrome(int x) {
        String str = String.valueOf(x);
        StringBuffer sb = new StringBuffer(str);
        String s = sb.reverse().toString();
        if(str.contains(s))
            return true;
        else
            return false;
    }
}


//将整数分成左右两部分,右边那部分需要转置,然后判断这两部分是否相等。
public boolean isPalindrome(int x) {
    if (x == 0) {
        return true;
    }
    if (x < 0 || x % 10 == 0) {
        return false;
    }
    int right = 0;
    while (x > right) {
        right = right * 10 + x % 10;
        x /= 10;
    }
    return x == right || x == right / 10;
}

6.计算二进制字串

力扣696:https://leetcode-cn.com/problems/count-binary-substrings/description/

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

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

示例 1 :

  • 输入: "00110011"
  • 输出: 6

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

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

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

  • 输入: "10101"
  • 输出: 4

解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。

代码实现:

class Solution {
    public int countBinarySubstrings(String s) {
        if(s==null || s.length()<2)    return 0;
        int count = 1;
        int len = s.length();
        List<Integer> list = new ArrayList();
        for(int i=0;i<len-1;i++){
            if(s.charAt(i)==s.charAt(i+1)){
                count++;
            }else{
                list.add(count);
                count = 1;
            }
        }
        list.add(count);
        len = list.size()-1;
        count = 0;
        for(int i=0;i<len;i++){
            count += Math.min(list.get(i),list.get(i+1));
        }
        return count;
    }
}

7.最短回文串

力扣214:https://leetcode-cn.com/problems/shortest-palindrome/

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

示例 1:

  • 输入: "aacecaaa"
  • 输出: "aaacecaaa"

示例 2:

  • 输入: "abcd"
  • 输出: "dcbabcd"

代码实现:

class Solution {
    public String shortestPalindrome(String s) {
        String r = new StringBuilder(s).reverse().toString();
        int len = s.length();
        int i=0;
        for(i=0;i<len;i++){
            if (s.substring(0, len - i).equals(r.substring(i))) {
                break;
            }
        }
        return new StringBuilder(s.substring(len-i)).reverse()+s;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值