Leetcode题解-数据结构-字符串

1、两字符的组成字符是否相等

242.Valid Anagram(Easy)
Given two strings s and t , write a function to determine if t is an anagram of s.

Example 1:

Input: s = “anagram”, t = “nagaram”
Output: true

Example 2:

Input: s = “rat”, t = “car”
Output: false

Note:
You may assume the string contains only lowercase alphabets.

Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?

问题分析:
给两个字符串,判断两个字符串是否有相同的字符组合。

方法一:
一共只有26个字母,建一个大小为26的数组,遍历字符串s,以字母的位置作为下标,每出现一次就将对应位置的数组中元素加1;再遍历字符串t,字母每出现一次就将对应位置的数组中元素减1。如果此时数组中元素都是0,返回true,有元素不是0,返回false。

class Solution {
public:
    bool isAnagram(string s, string t) {
        int a[26]={0};
        for(int i=0;i<s.size();i++)
            a[s[i]-'a']++;
         for(int i=0;i<t.size();i++)
            a[t[i]-'a']--;
        for(int i=0;i<26;i++)
            if(a[i]!=0)
                return false;
        return true;
    }
};

方法二:
首先判断两字符串长度是否相等,不相等返回false。将两个字符串中的字符排序,逐一比较,如果对应位置完全相等,返回true,否则返回fasle。

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size() != t.size())
            return false;
        sort(s.begin(), s.end());
        sort(t.begin(), t.end());
        return s == t;
    }
};

2、一组字符可以组成回文字符串最大长度

409. Longest Palindrome(Easy)
Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters.This is case sensitive, for example “Aa” is not considered a palindrome here.

Note:
Assume the length of given string will not exceed 1,010.

Example:

Input:
“abccccdd”
Output:
7

Explanation:
One longest palindrome that can be built is “dccaccd”, whose length is 7.

问题分析:
给一组字符,统计从这组字符中可以组成的回文字符串的最大长度。

首先统计每个字符出现的次数,将字符个数除以2,再乘以2,表示该字符的偶数个数,可以放在回文字符串中,奇数个数的字符只能放1个,如果有奇数个数的字符,将回文字符串长度再加1,结果即为可以组成的回文字符串的最大长度。

class Solution {
public:
    int longestPalindrome(string s) {
        int a[200]={0};
        int cnt=0;
        bool singlechar=false;
        for(int i=0;i<s.size();i++)
            a[s[i]-'A']++;
        for(int i=0;i<200;i++)
        {
            if(a[i]%2==1)
                singlechar=true;
            cnt+=(a[i]/2)*2;
        }
        if(singlechar)
            cnt=cnt+1;
        return cnt;
    }
};

3、字符串同构

205.Isomorphic Strings(Easy)
Given two strings s and t, determine if they are isomorphic.Two strings are isomorphic if the characters in s can be replaced to get t.

All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.

Example 1:

Input: s = “egg”, t = “add”
Output: true

Example 2:

Input: s = “foo”, t = “bar”
Output: false

Example 3:

Input: s = “paper”, t = “title”
Output: true

Note:
You may assume both s and t have the same length.

方法一:
对于每一个字符,寻找该字符在字符串中出现的第一个位置,如果两字符在两字符串中第一次出现的位置完全对应,则为同构字符串。

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        int lens=s.size();
        int lent=t.size();
        if(lens!=lent)
            return false;
        for(int i=0;i<lens;i++)
        {
            if(pos(s,s[i])!=pos(t,t[i]))
                return false;
        }
        return true;
    }
    
    int pos(string s,char c)
    {
        for(int i=0;i<s.size();i++)
        {
            if(s[i]==c)
                return i;
        }
        return -1;
    }
};

时间复杂度:O(n2)
空间复杂度:O(1)

方法二
使用 unordered_map,将 s 中每个元素作为 key 值,t 中对应元素为 value;将 t 中每个元素作为 key 值,s 中对应元素为 value。

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        if(s.size() != t.size())
            return false;
        unordered_map<char, char>m1, m2;
        for(int i = 0; i < s.size(); i++){
            if (m1.find(s[i]) != m1.end()){
                if (m1[s[i]] != t[i])
                    return false;
            }
            else
                m1[s[i]] = t[i];
            if (m2.find(t[i]) != m2.end()){
                if(m2[t[i]] != s[i])
                    return false;
            }
            else
                m2[t[i]] = s[i];
        }
        return true;
    }
    
};

时间复杂度:O(n)
空间复杂度:O(n)

4、回文子字符串的个数

647. Palindromic Substrings(Medium)
Given a string, your task is to count how many palindromic substrings in this string.

The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.

Example 1:

Input: “abc”
Output: 3
Explanation: Three palindromic strings: “a”, “b”, “c”.

Example 2:

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

Note:
The input string length won’t exceed 1000.

问题分析:
给一个字符串,判断该字符串中一共有多少个回文字符串(从前向后读和从后向前读一样)
如果回文字符串的长度为偶数,就从中间两个字符逐渐向外走,逐一匹配。
如果回文字符串的长度为奇数,就从中间一个字符逐渐向外走,逐一匹配。

class Solution {
public:
    int cnt=0;
    int countSubstrings(string s) 
    {
        int len=s.size();
        for(int i=0;i<len;i++)
        {
            extendstring(s,i,i);	//长度为奇数的回文字符串
            extendstring(s,i,i+1);	//长度为偶数的回文字符串
        }
        return cnt;
    }
    void extendstring(string s,int begin,int end)
    {
        while(begin>=0&&end<s.size()&&s[begin]==s[end])
        {
            begin--;
            end++;
            cnt++;
        }
    }
};

时间复杂度:O(n2)
空间复杂度:O(1)

5、判断一个数是不是回文数

9. Palindrome Number(Easy)
Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.

Example 1:

Input: 121
Output: true

Example 2:

Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.

Example 3:

Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.

Follow up:
Coud you solve it without converting the integer to a string?

问题分析:
判断一个整数是否是回文数,从前向后,从后向前读完全一样,不能把整数转化为字符串。

将整数分成前后两部分,将后面的那部分转置,然后判断前后两部分是否相等或者只差最后一位。

class Solution {
public:
    bool isPalindrome(int x) {
        if(x<0||x%10==0)    //负数,以0结尾的数
            return false;
        if(x==0)
            return true;
        int right=0;
        while(right<x)
        {
            right=right*10+x%10;
            x=x/10;
        }
        if(right==x||x==right/10)
            return true;
        else
            return false;
    }
};

时间复杂度 : O(log10(n))
​空间复杂度:O(1)

也可以变成字符串再判断是否回文

class Solution {
public:
    bool isPalindrome(int x) {
        string s = to_string(x);
        int i = 0, j = s.size() - 1;
        while (i < j){
            if(s[i] != s[j])
                return false;
            i++;
            j--;
        }
        return true;
    }
};

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

696.Count Binary Substrings(Easy)
Give a string s, count the number of non-empty (contiguous) substrings that have the same number of 0’s and 1’s, and all the 0’s and all the 1’s in these substrings are grouped consecutively.

Substrings that occur multiple times are counted the number of times they occur.

Example 1:

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”.

Notice that some of these substrings repeat and are counted the number of times they occur.

Also, “00110011” is not a valid substring because all the 0’s (and 1’s) are not grouped together.

Example 2:

Input: “10101”
Output: 4
Explanation: There are 4 substrings: “10”, “01”, “10”, “01” that have equal number of consecutive 1’s and 0’s.

Note:
s.length will be between 1 and 50,000.
s will only consist of “0” or “1” characters.

问题分析:
一个二进制字符串只有 0 和 1 组成,现在需要统计二进制字符串中连续 1 和连续 0 数量相同的子字符串个数,所有的 1 和所有的 0 必须连续,而且 0 和 1 的个数必须相等。在字符串的不同位置如果找出的连续字串相同,个数累加。
方法一:
现在将原字符串中从前向后将连续0和连续1的个数统计出来,比如 s = “110001111000000”, 统计出来连续 0,连续 1 的个数为vec= [2, 3, 4, 6]。遍历该数组,该数组中相邻的两数字中取最小值,累加起来就是要求解的答案。也就是求解 min(vec[i-1], vec[i]) 之和。

class Solution {
public:
    int countBinarySubstrings(string s) {
        int n=s.size();
        vector<int>vec(n,0);
        int count=0;
        int cnt=0;
        vec[0]=1;
        for(int i=1;i<n;i++)
        {
            if(s[i-1]==s[i])
                vec[count]++;
            else
            {
                count++;
                vec[count]=1;
            }
        }
        int lenvec=vec.size();
        for(int i=1;i<lenvec;i++)
        {
            cnt=cnt+min(vec[i-1],vec[i]);
        }
        return cnt;
    }
};

方法二:
修改前面的方法,我们没必要保存连续的0,1出现的次数,我们只需要知道当前连续的数字出现的次数和上次连续数字出现的次数,取最小值即可。

class Solution {
public:
    int countBinarySubstrings(string s) {
        int n=s.size();
        int prev=0,cur=1;
        int sum=0;
        for(int i=1;i<n;i++)
        {
            if(s[i-1]!=s[i])
            {
                sum+=min(prev,cur);
                prev=cur;
                cur=1;
            }
            else
                cur++;
        }
        return sum+min(prev,cur);//最后一个连续的数字没有计算
    }
};

7、旋转字符串

796. Rotate String(Easy)
判断字符串 A 旋转后是否可以变为 B 字符串

Example 1:

Input: A = ‘abcde’, B = ‘cdeab’
Output: true

Example 2:

Input: A = ‘abcde’, B = ‘abced’
Output: false

方法一:暴力搜索
外层循环表示 A 的偏移量,内层循环表示从字符串 B 的第一个字符依次向后匹配,如果能匹配到最后一个元素,表示匹配成功。

class Solution {
public:
    bool rotateString(string A, string B) {
        if (A == "" && B == "") return true;
        if (A.size() != B.size()) return false;
        int n = A.size();
        for (int i = 0; i < n; i++){
            int j;
            for (j = 0 ; j < n; j++){
                if (A[(i + j) % n] != B[j])
                    break;
            }
            if(j == n)
                return true;
        }
        return false;
    }
};

时间复杂度:O(n2)
空间复杂度:O(1)

方法二
获取字符串后面 n - i 个字符加上前面 i 个字符,就得出旋转之后的字符,再比较是否相等即可。

class Solution {
public:
    bool rotateString(string A, string B) {
        if(A == "" && B == "") return true;
        if (A.size() != B.size()) return false;
        int n = A.size();
        for(int i = 0; i < n; i++){
            string s = A.substr(i, n - i) + A.substr(0, i);
            if(s == B) return true;
        }
        return false;
    }
};

方法三:KMP

class Solution {
public:
    bool rotateString(string A, string B) {
        if(A == "" && B == "") return true;
        if (A.size() != B.size()) return false;
        int n = A.size();
        A = A +A;
        if(KmpSearch(A, B) == -1) return false;
        return true;
    }
    void GetNext(string p, int next[]) {
        int pLen = p.size();
        next[0] = -1;
        int k = -1;
        int j = 0;
        while (j < pLen - 1) {
            if (k == -1 || p[j] == p[k]) {  
                ++k;  
                ++j;  
                next[j] = k;  
            }  
            else   
                k = next[k];
        }  
    }
    int KmpSearch(string s, string p) {  
        int i = 0;  
        int j = 0;
        int next[20000];
        GetNext(p, next); 
        int sLen = s.size();
        int pLen = p.size();
        while (i < sLen && j < pLen) {   
            if (j == -1 || s[i] == p[j]) {  
                i++;  
                j++;  
            }  
            else  
                j = next[j];
        }
        if (j == pLen)  
            return i - j;
        else  
            return -1;
    }  
};

时间复杂度:O(n)
空间复杂度:O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值