leetcode
leetcode 2051 ~ 2100
最大回文数字

最大回文数字

难度:

标签:

题目描述

代码结果

运行时间: 45 ms, 内存: 16.7 MB


/*
 * Approach using Java Streams:
 * 1. Count the frequency of each digit using groupingBy and counting.
 * 2. Build the half palindrome by flatMapping digits.
 * 3. Determine if there is a center digit with odd frequency.
 * 4. Combine the half, center (if any), and reversed half to form the full palindrome.
 */

import java.util.Map;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.stream.IntStream;

public class MaxPalindromeStream {
    public static String largestPalindrome(String num) {
        // Count frequency of each digit
        Map<Character, Long> count = num.chars()
                .mapToObj(c -> (char) c)
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        // Construct the half palindrome and find the center if any
        StringBuilder half = new StringBuilder();
        Character center = null;

        count = count.entrySet().stream()
                .sorted(Map.Entry.<Character, Long>comparingByKey(Comparator.reverseOrder()))
                .collect(Collectors.toMap(
                        Map.Entry::getKey, Map.Entry::getValue,
                        (e1, e2) -> e1, LinkedHashMap::new));

        for (Map.Entry<Character, Long> entry : count.entrySet()) {
            char digit = entry.getKey();
            long cnt = entry.getValue();
            if (cnt % 2 == 1 && (center == null || digit > center)) {
                center = digit;
            }
            half.append(String.valueOf(digit).repeat((int) (cnt / 2)));
        }

        // Avoid leading zeroes
        if (half.length() == 0 && center != null && center == '0') {
            return "0";
        }

        // Construct the largest palindrome
        String halfStr = half.toString();
        String palindrome = halfStr;
        if (center != null) {
            palindrome += center;
        }
        palindrome += new StringBuilder(halfStr).reverse().toString();
        return palindrome;
    }

    public static void main(String[] args) {
        System.out.println(largestPalindrome("444947137")); // Output: 7449447
        System.out.println(largestPalindrome("00009")); // Output: 9
    }
}

解释

方法:

此题解的思路基于统计输入字符串中每个数字的出现次数。首先,创建一个计数数组c来统计字符串中每个数字的数量。接着,根据每个数字的数量,计算出每个数字可以形成的对数(即最大的偶数次),以及剩余的是否能为中心字符(奇数次的存在)。为构造最大的回文数字,从最大的数字(9)到最小的数字(0)进行遍历,优先使用数字对形成回文的两侧。如果存在奇数次的数字,选择最大的一个作为回文的中心。特别注意,如果所有的偶数部分数字为'0'且没有奇数中心,应直接返回'0'以避免前导零问题。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在构建回文数字时,为什么选择最大的奇数数字作为中心,而不是选择其他的奇数数字?
在构建最大的回文数字时,选择最大的奇数数字作为中心可以确保生成的回文数值尽可能大。由于回文结构中心的数字只能单独存在,因此使用最大的奇数数字作为中心可以有效地增加整个回文数的数值。例如,如果中心能选择9而选择了1,那么最终的回文数字将显著变小。
🦆
解决方案中提到如果所有偶数部分数字为'0'且没有奇数中心时应直接返回'0',那么如果存在奇数中心但偶数部分全为'0',应该如何处理?
如果存在奇数中心但偶数部分全为'0',则应构建回文数使其只包含这个奇数中心。例如,如果中心是3而偶数部分全为0,则回文数应为'3'。这种情况下,不会有前导零问题,因为只有一个数字构成回文。
🦆
为什么在构建回文时选择从数字9到0逆序添加,这种方法是否总是保证结果是最大的回文数?
从数字9到0逆序添加数字到回文的两端确保了构建的回文数是最大可能的值。因为回文是对称的,所以在每侧从大到小添加相同数量的数字,可以最大化回文数的数值。这种方法保证了在给定数字的限制下,构建的回文数总是最大的。
🦆
在代码中检查字符串ee是否以'0'开头来避免前导零,这种方法是否足够可靠?有没有可能出现误判的情况?
此方法通常是可靠的,因为如果ee以'0'开头,则意味着所有较大的数字都未能形成对,而只有数字0形成了对。在没有其他数字的情况下,如果ee仅包含'0',则整个字符串应该只返回'0',以避免前导零问题。这种情况下,检查是否以'0'开头足以判断是否需要返回'0',因此不会发生误判。

相关问题