leetcode 409. 最长回文串

https://leetcode-cn.com/problems/longest-palindrome/
在这里插入图片描述
并不需要去构造一个回文串,只需要返回长度即可
思考了一下,找了个规律:

  1. 如果当前字符个数总和是偶数,则不能存在任何字符的个数是奇数
  2. 如果当前字符个数总和是奇数,则只能存在一个奇数

那么我们先建一个字典,然后遍历字典

  1. 统计字符数总和
  2. 统计字符数是奇数的字符
  3. 统计字符数是奇数的字符个数

遍历一遍之后,判断上面两条规律是否满足,只要满足其中一条,那么当前肯定是最大回文串
如果不满足,无论如何都要减去一个是奇数的字符个数,因为奇数-1之后,肯定就是偶数了,接着重新遍历即可(总会把所有奇数变成偶数)
一开始我想的是减少那个最小的key,但是好像不对
例如a=2,b=2,c=3,d=1的情况,如果直接减去c=3的话,那么就成立了,如果减去d=1的话,那么就还是不成立,就错过最大回文子串了
所以只需要减去第一个是奇数的字符就行了

class Solution:
    def longestPalindrome(self, s: str) -> int:
        #不需要真的组成一个串
        #总长度为偶数的回文串,每个元素必须都是偶数
        #总长度为奇数的回文串,最多一个元素是奇数,其余都是偶数
        #直接从最长的长度判断
        #如果可以满足以上两个条件,则成功
        #减去一个key为奇数的值
        dct = dict()
        for ch in s:
            dct[ch] = dct.get(ch, 0) + 1
        while True:
            size = 0
            oddnum = 0
            oddnumLst=[]
            flag = True
            for i, j in dct.items():
                size += j
                if j % 2 != 0:
                    oddnum += 1
                    oddnumLst.append(i)
            if size % 2 == 0:  # 是偶数长度,不能有偶数
                if oddnum > 0:  # 如果出现奇数
                    flag = False
            elif size % 2 != 0:  # 是奇数长度,只能有一个奇数
                if oddnum != 1:
                    flag = False
            if flag:
                return size
            else:
                # 减少第一个奇数个数
                dct[oddnumLst[0]]-=1
                if dct[oddnumLst[0]] == 0:
                    del dct[oddnumLst[0]]

在这里插入图片描述
后面看了一下提交记录,发现一年前自己已经做过了

class Solution {
public:
    int longestPalindrome(string s) {
        int mp[52]={0};
        for(char ch:s){
            if(ch<='z'&&ch>='a')
                mp[ch-'a']++;
            else
                mp[ch-'A'+26]++;
        }
        int ans=0;
        int odd=0;
        for(int i=0;i<52;i++){
            ans+=mp[i];
            if(mp[i]%2!=0)
                odd++;
        }
        if(odd!=0) ans-=odd-1;
        return ans;
    }
};

在这里插入图片描述
思路是这样的,也是统计总个数,然后再统计出现个数是奇数的字符个数
假如有max个字符是奇数,我们只能留一个奇数来构成回文字符串,而把一个奇数变为偶数需要减1
所以最终的答案要减去max-1个1

贴一下别人比较好理解的代码
java

class Solution {
    public int longestPalindrome(String s) {
      int[] cnt = new int[58];
      for (char c : s.toCharArray()) {
        cnt[c - 'A'] += 1;
      }

      int ans = 0;
      for (int x: cnt) {
        // 字符出现的次数最多用偶数次。
        ans += x - (x & 1);
      }
      // 如果最终的长度小于原字符串的长度,说明里面某个字符出现了奇数次,那么那个字符可以放在回文串的中间,所以额外再加一。
      return ans < s.length() ? ans + 1 : ans;  
    }
}
https://leetcode-cn.com/problems/longest-palindrome/solution/javade-2chong-shi-xian-fang-fa-by-sweetiee/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值