leetcode
leetcode 2351 ~ 2400
字典序最小回文串

字典序最小回文串

难度:

标签:

题目描述

You are given a string s consisting of lowercase English letters, and you are allowed to perform operations on it. In one operation, you can replace a character in s with another lowercase English letter.

Your task is to make s a palindrome with the minimum number of operations possible. If there are multiple palindromes that can be made using the minimum number of operations, make the lexicographically smallest one.

A string a is lexicographically smaller than a string b (of the same length) if in the first position where a and b differ, string a has a letter that appears earlier in the alphabet than the corresponding letter in b.

Return the resulting palindrome string.

 

Example 1:

Input: s = "egcfe"
Output: "efcfe"
Explanation: The minimum number of operations to make "egcfe" a palindrome is 1, and the lexicographically smallest palindrome string we can get by modifying one character is "efcfe", by changing 'g'.

Example 2:

Input: s = "abcd"
Output: "abba"
Explanation: The minimum number of operations to make "abcd" a palindrome is 2, and the lexicographically smallest palindrome string we can get by modifying two characters is "abba".

Example 3:

Input: s = "seven"
Output: "neven"
Explanation: The minimum number of operations to make "seven" a palindrome is 1, and the lexicographically smallest palindrome string we can get by modifying one character is "neven".

 

Constraints:

  • 1 <= s.length <= 1000
  • s consists of only lowercase English letters.

代码结果

运行时间: 65 ms, 内存: 16.2 MB


/*
题目思路:
1. 使用Stream API来处理字符串,可以通过CharArray进行流操作。
2. 逐个比较字符串的前后字符,如果不同,则将字典序较小的字符替换字典序较大的字符。
3. 从字符串的两端向中间进行这样的操作,直到全部字符对称为止。
*/

import java.util.stream.IntStream;

public class Solution {
    public String makePalindrome(String s) {
        char[] arr = s.toCharArray();
        IntStream.range(0, arr.length / 2)
                 .forEach(i -> {
                     if (arr[i] != arr[arr.length - 1 - i]) {
                         if (arr[i] < arr[arr.length - 1 - i]) {
                             arr[arr.length - 1 - i] = arr[i];
                         } else {
                             arr[i] = arr[arr.length - 1 - i];
                         }
                     }
                 });
        return new String(arr);
    }
}

解释

方法:

解题思路是通过两个指针从字符串的两端向中间遍历,比较对应的字符。如果两个字符不同,则选择两者中较小的字符来替换较大的字符,以此来确保最终结果的字典序尽可能小。这样操作直到两个指针相遇或者交错,最后的字符串就是字典序最小的回文串。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在字符不同的情况下,总是选择较小的字符替换较大的字符?这样的选择对结果的字典序大小有什么影响?
在构造字典序最小的回文串时,选择较小的字符替换较大的字符是为了确保所形成的回文串尽可能小。字典序是按字符从左到右比较的,较小的字符会使得整个字符串的字典序更小。通过这种方法,可以在保证字符串是回文的同时,也确保了其在所有可能的回文串中字典序最小。
🦆
在比较和替换字符时,如果字符相同,这种情况下算法如何处理?题解中似乎没有提及。
如果在遍历过程中两个指针指向的字符相同,实际上不需要进行任何操作,因为这两个字符已经满足了回文串的对称性要求。算法只需继续移动指针,检查下一对字符。
🦆
题解中提到,只遍历字符串的一半就可以完成转换,请问这种方法处理字符串长度为奇数和偶数时有什么不同吗?
无论字符串长度是奇数还是偶数,遍历到字符串的一半即可完成回文的构造,因为回文串是关于中心对称的。对于偶数长度的字符串,每个字符都有对应的对称字符;对于奇数长度的字符串,中间的字符不需要对称,它自己即是中心点。因此,算法只需关注对称的字符是否一致或调整到一致即可。
🦆
在实际的字符替换操作中,是否考虑了所有可能的边界情况,例如字符串中所有字符相同,或者字符串已经是一个回文串的情况?
本算法确实考虑了这些边界情况。如果字符串中所有字符相同,则每次比较的字符都是相同的,算法不会进行任何替换操作,直接返回原字符串即可。如果字符串已经是一个回文串,同样由于每次比较的字符相同或正确对称,不需要替换,算法也会直接返回原字符串。这些情况下算法的表现是正确且高效的。

相关问题