每日一题-1.最长回文串

题目:

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

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

注意:

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

实例1:
输入:
"abccccdd"

输出:
7

解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
思考一:

简单思路,字符成对出现,将字符依次放入到list中,发现list中有该元素,移除并给当前回文串长度+2,最后查看list中是否还有值,有回文串长度为count+1,没有则是count。

import java.util.ArrayList;
import java.util.List;

class Solution {
   
      public static int longestPalindrome(String s) {
         char ch[] = s.toCharArray();
         List<Character> list = new ArrayList<>();
         int count = 0 ;
         for (int i = 0; i < ch.length; i++) {
             if(list.contains(ch[i])){
                 remove(list,ch[i]);
                 count = count + 2;
             }else {
                 list.add(ch[i]);
             }
         }
         if(list.isEmpty()){
             return count;
         }
         return count+1;
    }

    public static void remove(List<Character> list, Character target){
        for(int i = list.size() - 1; i >= 0; i--){
            Character item = list.get(i);
            if(target.equals(item)){
                list.remove(item);
            }
        }
    }
}

虽然运行通过了,但是结果不是那么的完美

执行用时 :11 ms, 在所有 Java 提交中击败了19.96%的用户
内存消耗 :37.6 MB, 在所有 Java 提交中击败了5.25%的用户

对此进行进一步的优化。

思考二:

使用map的特性

import java.util.HashMap;
import java.util.Map;

class Solution {
   
public static int longestPalindrome(String s) {
        char ch[] = s.toCharArray();
        Map<Character,Integer> map = new HashMap<>();
        int count = 0;
        for (int i = 0; i < ch.length; i++) {
            if(map.containsKey(ch[i])){
                map.remove(ch[i]);
                count += 2;
            }else {
                map.put(ch[i],1);
            }
        }
        if(!map.isEmpty()){
            return count+1;
        }
        return count;
    }
}
执行用时 :7 ms, 在所有 Java 提交中击败了35.71%的用户
内存消耗 :38.4 MB, 在所有 Java 提交中击败了5.25%的用户

除了执行耗时进行了稍微提升之外没有其他的提升。

思考三:

以上两个方法都是都是统计对称字符的个数来计算回文串的长度,添加和移除操作难免会有时间复杂度的提升以及内存消耗的提示。
‘A’ - ‘A’ = 0
‘z’ - ‘A’ = 57
根据字符这一个特性,我们可以建立一个长度为58的数组,用下标的形式对应每一个字符。

class Solution {
    public int longestPalindrome(String s) {
        int[] chs = new int[58];
         for (int i = 0; i < s.length(); i++) {
             chs[s.charAt(i) - 'A']++;
         }
         int count = 0;
         for (int ch : chs) {
             count += (ch / 2) * 2;
         }
         if (count < s.length()) {
             count ++;
         }
         return count;
     }
}
执行用时 :4 ms, 在所有 Java 提交中击败了42.93%的用户
内存消耗 :37.5 MB, 在所有 Java 提交中击败了5.25%的用户

看到这个结果是有点不满意的,没有啥新的想法,看看代码怎么优化吧

class Solution {
    public int longestPalindrome(String s) {
        int[] chs = new int[58];
         for (int i = 0; i < s.length(); i++) {
             chs[s.charAt(i) - 'A']++;
         }
         int count = 0;
         for (int ch : chs) {
             count += (ch/2)*2;
         }
         return count<s.length()?count+1:count;
     }
}

果然,对代码进行了简单的优化,结果是不同的

执行用时 :2 ms, 在所有 Java 提交中击败了76.48%的用户
内存消耗 :37.7 MB, 在所有 Java 提交中击败了5.25%的用户

今日一题结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值