[杨小白]_leetcode_2131. 连接两字母单词得到的最长回文串

75 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标300题,记录从0到1的全过程!!

2131. 连接两字母单词得到的最长回文串

这是69场双周赛的第三题

2131. 连接两字母单词得到的最长回文串

给你一个字符串数组 words 。words 中每个元素都是一个包含 两个 小写英文字母的单词。

请你从 words 中选择一些元素并按 任意顺序 连接它们,并得到一个 尽可能长的回文串 。每个元素 至多 只能使用一次。

请你返回你能得到的最长回文串的 长度 。如果没办法得到任何一个回文串,请你返回 0 。

回文串 指的是从前往后和从后往前读一样的字符串。

示例 1

输入:words = ["lc","cl","gg"]

输出:6

解释:一个最长的回文串为 "lc" + "gg" + "cl" = "lcggcl" ,长度为 6 。

"clgglc" 是另一个可以得到的最长回文串。

示例 2

输入:words = ["ab","ty","yt","lc","cl","ab"]

输出:8

解释:最长回文串是 "ty" + "lc" + "cl" + "yt" = "tylcclyt" ,长度为 8 。

"lcyttycl" 是另一个可以得到的最长回文串。

示例 3

输入:words = ["cc","ll","xx"]

输出:2

解释:最长回文串是 "cc" ,长度为 2 。

"ll" 是另一个可以得到的最长回文串。"xx" 也是。

提示:

  • 1 <= words.length <= 105
  • words[i].length == 2
  • words[i] 仅包含小写英文字母

2.解法一 HashMap

class Solution {
    public int longestPalindrome(String[] words) {
        HashMap<String, Integer> map = new HashMap<>();
        int t = 0;
        int same = 0;
        for(int i = 0; i < words.length; i++) {
            String reverse = ""+words[i].charAt(1) + words[i].charAt(0);
            if(map.containsKey(reverse)) {
                t= t+2;
                if(map.get(reverse) == 1) {
                    map.remove(reverse);
                } else {
                    map.put(reverse,map.get(reverse)-1);
                }
            } else {
                if(map.containsKey(words[i])) {
                    map.put(words[i],map.get(words[i])+1);
                } else {
                    map.put(words[i],1);
                }
            }
        }
        for(String s : map.keySet()) {
            if(s.charAt(0)==s.charAt(1)) {
                same++;
                break;
            }
        }
        return (t + same) * 2;
    }
}

提交排名

image.png

解析

这个题最低也是O(n)的时间复杂度,那就首先for循环遍历整个数组,关键是怎么判断遍历的这个对应的字符,能不能添加到最后的结果中呢?

这里我引入了一个hashmap,他的key就是字符对,value是这个字符还有几次没用。

第一步,对于任意一个字符"ab",我们去hashmap中找有没有"ba",如果找到了,结果t++,并把"ba"对应的值--;如果没有找到就把"ab"放入map中,遍历完之后,map中存放的就是没有对应的字符串了。

第二步,遍历map,找到是否存在"aa"类型的字符串,如果找到就讲same++;并且直接返回。

第三步,返回结果t+same的两倍就可以了。

2.解法二 数组

class Solution {
    public int longestPalindrome(String[] words) {
        char[][] chars = new char[26][26];
        int t = 0;
        int same = 0;
        for(int i = 0; i < words.length; i++) {
            int c1 = words[i].charAt(0) - 'a';
            int c2 = words[i].charAt(1) - 'a';
            if(chars[c2][c1]>0) {
                t = t + 2;
                chars[c2][c1]--;
            } else {
                chars[c1][c2]++;
            }
        }
        for (int i = 0; i < 26; i++) {
            if(chars[i][i]>0) {
                same++;
                break;
            }
        }
        return (t + same) * 2;
    }
}

提交排名

image.png

解析

map的添加删除查询等操作确实太多了,会导致运行时间过长,因为字母数量是26个优先的,那所有字符串也都可以包含在char[26][26]的数组中,这样用这样的二维数组代替map,就可以使得运行效率更高了。

3.结束

这个题作为当时周赛的第三题,并不算难,周赛的时候能用map来ac也是可以的,map的思路容易想到,但是实现起来还是比数组要复杂一些。gogogo,刷题刷题,每天一道,三年1000道!!!!