[题解] 《算法零基础100讲》(第26讲) 字符串算法(六) - 回文串

面试题 01.04. 回文排列

线性枚举+计数

给定一个串,看他能否变成一个回文串。那么我们就来观察回文串的结构,如果回文串的长度是偶数,那么说明他的前半段和后半段是完全相同的,换言之每一个字符在串中出现次数都是偶数(因为一个字符可能在串的半段中就多次出现);如果回文串的长度是奇数,也仅有可能中间一个字符出现的次数是奇数次。所以我们可以按照这个规律对每一个字符出现的次数进行计数

class Solution {
public:
    bool canPermutePalindrome(string s) {
        unordered_map<char,int>mp;
        int one=0;
        for(int i=0;i<s.size();i++)
        {
            mp[s[i]]++;
        }
        for(auto t:mp)
        {
            if(t.second%2) one++;
            if(one>1) return false;
        }
        return true;
    }
};

剑指 Offer II 018. 有效的回文

双指针

整合一下需要考虑的部分为一个新串,然后用双指针从定义出发来判断是不是回文串

class Solution {
    bool check(string ch)
    {
        int i=0,j=ch.size()-1;
        while(i<j)
        {
            if(ch[i]!=ch[j]) return false;
            i++,j--;
        }
        return true;
    }
public:
    bool isPalindrome(string s) {
        string ch;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]>='A'&&s[i]<='Z') ch+=s[i]+32;
            else if(s[i]>='a'&&s[i]<='z') ch+=s[i];
            else if(s[i]>='0'&&s[i]<='9') ch+=s[i];
        }
        return check(ch);
    }
};

409. 最长回文串

贪心

根据回文串的定义(第一题中有说明)我们呢总是可以有这样一种贪心策略:对每一个字符计数,只加他的偶数部分。最后如果还有剩余,加上一个字母作为中心回文轴(看了官解除2乘2好妙)

class Solution {
public:
	int longestPalindrome(string s) {
		unordered_map<char, int> mp;
		int ans = 0;
		for (char t:s)
			mp[t]++;
		for (auto t:mp) 
        {
			int v=t.second;
			ans+=v/2*2;
			if (v%2==1&&ans%2==0)
				ans++;
		}
		return ans;
	}
};

剑指 Offer II 019. 最多删除一个字符得到回文

线性枚举+双指针

遍历字符串,当找到对称位置的字符不同时,就分别判断删掉左边的字符和删掉右边的字符

class Solution {
    bool check(string ch,int n)
    {
        int i=0,j=ch.size()-1;
        while(i<j)
        {
            if(i==n) i++;
            if(j==n) j--;
            if(ch[i]!=ch[j]) return false;
            i++,j--;
        }
        return true;
    }
public:
    bool validPalindrome(string s) {
        int l=0,r=s.size()-1;
        while(l<r)
        {
            if(s[l]!=s[r]) return check(s,l)||check(s,r);
            l++,r--;
        }
        return true;
    }
};

1332. 删除回文子序列

找规律

观察发现因为字符串中只有两种字符,所以答案其实只有三种。0:如果字符串的长度为0,则答案是0;1:如果字符串本身就是一个回文串,那么一次就可以全删掉;2:如果字符串不是回文串,那么他就一定可以分成若干个a和若干个b

class Solution {
public:
    int check(string ch)
    {
        int l=0,r=ch.size()-1;
        while(l<r)
        {
            if(ch[l]!=ch[r]) return 2;
            l++,r--;
        }
        return 1;
    }
    int removePalindromeSub(string s) {
        return !s.size()?0:check(s);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习算法的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值