算法题目 字符串操作

目录

        • 循环移位
        • 两个字符串包含的字符是否相同
        • 计算一组字符集合可以组成的回文字符串的最大长度
        • 同构字符串
        • 一个字符串中连续回文子字符串的个数
        • 判断一个整数是否是回文数
        • 统计二进制字符串中连续 1 和连续 0 数量相同的连续子字符串个数


循环移位

循环移位可以通过部分翻转然后整体翻转来完成

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

s1 = AABCD, s2 = CDAA
Return : true

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

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

s = “abcd123” k = 3
Return “123abcd”

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

字符串中单词的翻转

s = “I am a student”
Return “student a am I”

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


两个字符串包含的字符是否相同

leetcode 242 有效的字母异位词(简单)
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1:

输入: s = “anagram”, t = “nagaram”
输出: true

示例 2:

输入: s = “rat”, t = “car”
输出: false

说明:
你可以假设字符串只包含小写字母。

题解:
常规词频统计

class Solution {
    public boolean isAnagram(String s, String t) {
        int n = s.length();
        int m = t.length();
        if(n != m){
            return false;
        }
        
        int[] freqS = new int[26];
        int[] freqT = new int[26];
        
        for(int i=0; i

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

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

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

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

示例 1:

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

题解:

class Solution {
    public int longestPalindrome(String s) {
        int res = 0;
        
        // 词频统计
        int[] freq = new int[256];
        for(char c: s.toCharArray()){
            freq[c]++;
        }
        
        for(int i: freq){
            i = i/2*2;  // 向下取偶
            res+=i;
        }
        
        if(res

同构字符串

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

leetcode 205 同构字符串(简单)
给定两个字符串 s 和 t,判断它们是否是同构的。

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

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

示例 1:

输入: s = “egg”, t = “add”
输出: true

示例 2:

输入: s = “foo”, t = “bar”
输出: false

示例 3:

输入: s = “paper”, t = “title”
输出: true

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

题解:
使用一个hashmap记录

class Solution {
    public boolean isIsomorphic(String s, String t) {
        if(s.length() != t.length()){
            return false;
        }
        
        HashMap map = new HashMap<>();
        for(int i=0; i

使用两个数组分别记录当前字符上次出现的位置

class Solution {
    public boolean isIsomorphic(String s, String t) {
        if(s.length() != t.length()){
            return false;
        }
        
        int n = s.length();
        // 分别记录当前字符上次出现的位置, 等于0时表示第一次出现
        int[] sLastIndexOf = new int[256];
        int[] tLastIndexOf = new int[256];
        
        for(int i=0; i

一个字符串中连续回文子字符串的个数

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

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

示例 1:

输入: “abc”
输出: 3
解释: 三个回文子串: “a”, “b”, “c”.

示例 2:

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

注意:

  • 输入的字符串长度不会超过1000。

题解:
从字符串的某一位开始,尝试向两边去扩展子字符串

class Solution {
    private int res;
    
    public int countSubstrings(String s) {
        for(int i=0; i=0 && end

动态规划, 相比于上述解法,时间性能差了许多

class Solution {
    public int countSubstrings(String s) {
        int res = 0;
        int n = s.length();
        
        // dp[i][j] 表示[i,j]的字符是否为回文子串
        boolean[][] dp = new boolean[n][n];
        
        // 注意,外层循环要倒着写,内层循环要正着写
        // 因为要求dp[i][j] 需要知道dp[i+1][j-1]
        for(int i=n-1; i>=0; i--){ 
            for(int j=i; j

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

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

示例 1:

输入: 121
输出: true

示例 2:

输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

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

题解:
要求不能使用额外空间,也就不能将整数转换为字符串进行判断。
将整数分成左右两部分,右边那部分需要转置,然后判断这两部分是否相等。

class Solution {
    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 = x/10;
        }
        
        return x==right || x==right/10;
    }
}

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

leetcode 696 计数二进制子串(简单)
给定一个字符串 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。

注意:

  • s.length 在1到50,000之间。
  • s 只包含“0”或“1”字符。

题解:

class Solution {
    public int countBinarySubstrings(String s) {
        int res = 0;
        
        int lastLen = 0;  // 记录之前的连续相同的字符的长度
        int curLen = 1;   // 记录当前连续相同的字符的长度
        
        for(int i=1; i

参考:Cyc2018 算法

你可能感兴趣的:(算法基础)