【算法思考记录】力扣2697. 字典序最小回文串【贪心字符串、Java、Py3、C++、Go、Rust、JS、TS】

原题链接


字典序最小回文串的算法解析

题目概述

给定一个由小写英文字母组成的字符串s,要求通过最少的字符替换次数,将其转换为一个字典序最小的回文串。回文串是指正着读和反着读都一样的字符串。

解题思路

核心思路

核心思路是将字符串s的前半部分与后半部分进行比较,并根据字典序进行适当的字符替换,以达到回文串的要求。

算法步骤

  1. 计算字符串s的长度n
  2. 遍历字符串s的前半部分,即遍历从开始到n/2的位置。
  3. 在每次遍历中,比较当前位置i的字符left和对称位置n-i-1的字符right
    • 如果left大于right,说明为了保持字典序最小,应该将left替换为right
    • 否则,将right替换为left
  4. 组合修改后的字符序列,返回结果。

代码注释

Python 版本
class Solution:
    def makeSmallestPalindrome(self, s: str) -> str:
        n = len(s)  # 计算字符串长度
        s = list(s)  # 转换为字符列表,方便修改
        for i in range(n // 2):  # 遍历字符串的前半部分
            left = s[i]  # 获取当前位置的字符
            right = s[-1 - i]  # 获取对称位置的字符
            if left != right:  # 如果两个字符不相等
                if left > right:  # 如果左边字符的字典序大于右边
                    s[i] = right  # 替换左边字符
                else:
                    s[-1 - i] = left  # 否则替换右边字符
        return ''.join(s)  # 返回修改后的字符串
Java 版本
class Solution {
    public String makeSmallestPalindrome(String s) {
        char[] char_s = s.toCharArray();  // 将字符串转换为字符数组
        for (int i = 0, j = s.length() - 1; i < s.length() / 2; i++, j--) {
            char left = char_s[i], right = char_s[j];  // 获取当前和对称位置的字符
            if (left > right) {
                char_s[i] = right;  // 字典序大的字符替换为小的
            } else {
                char_s[j] = left;  // 反之亦然
            }
        }
        return new String(char_s);  // 返回结果字符串
    }
}
C++ 版本
class Solution {
public:
    string makeSmallestPalindrome(string s) {
        int n = s.length();  // 字符串长度
        for (int i = 0, j = n - 1; i < n / 2; i++, j--) {
            char left = s[i], right = s[j];  // 获取当前和对称位置的字符
            if (left > right) {
                s[i] = right;  // 字典序大的字符替换为小的
            } else {
                s[j] = left;  // 反之亦然
            }
        }
        return s;  // 返回结果字符串
    }
};
Go 版本
func makeSmallestPalindrome(s string) string {
    char_s := []byte(s)  // 将字符串转换为字节切片
    for i, j := 0, len(s) - 1; i < len(s) / 2; i, j = i + 1, j - 1 {
        left, right := s[i], s[j]  // 获取当前和对称位置的字符
        if left > right {
            char_s[i] = right  // 字典序大的字符替换为小的
        } else {
            char_s[j] = left  //

 反之亦然
        }
    }
    return string(char_s)  // 返回结果字符串
}
TypeScript 版本
function makeSmallestPalindrome(s: string): string {
    const char_s = s.split('');  // 将字符串分割为字符数组
    for (let i = 0, j = s.length - 1; i < j; i++, j--) {
        let left = char_s[i], right = char_s[j];  // 获取当前和对称位置的字符
        if (left > right) {
            char_s[i] = right;  // 字典序大的字符替换为小的
        } else {
            char_s[j] = left;  // 反之亦然
        }
    }
    return char_s.join('');  // 返回结果字符串
};
JavaScript 版本
/**
 * @param {string} s
 * @return {string}
 */
var makeSmallestPalindrome = function(s) {
    let n = s.length;  // 字符串长度
    for (let i = 0, j = n - 1; i < j; i++, j--) {
        let left = s[i], right = s[j];  // 获取当前和对称位置的字符
        if (left > right) {
            s[i] = right;  // 字典序大的字符替换为小的
        } else {
            s[j] = left;  // 反之亦然
        }
    }
    return s;  // 返回结果字符串
};
Rust 版本
impl Solution {
    pub fn make_smallest_palindrome(s: String) -> String {
        let mut char_s: Vec<char> = s.chars().collect();  // 将字符串转换为字符向量
        let n = char_s.len();  // 字符串长度
        for i in 0..n / 2 {
            let j = n - 1 - i;
            let left: char = char_s[i];
            let right: char = char_s[j];
            if left > right {
                char_s[i] = right;  // 字典序大的字符替换为小的
            } else {
                char_s[j] = left;  // 反之亦然
            }
        }
        char_s.into_iter().collect()  // 返回结果字符串
    }
}
Rust代码解读与Rust特性分析
  1. 类型安全与明确性:
    Rust 强调类型安全和明确性,这在函数签名中体现得淋漓尽致。例如,pub fn make_smallest_palindrome(s: String) -> String 明确指出函数接受一个 String 类型的参数并返回一个 String 类型的结果。

  2. 所有权与借用机制:
    在 Rust 中,所有权(ownership)和借用(borrowing)机制是核心概念。本例中,函数接受一个属于调用者的 String 类型参数。一旦传递给函数,所有权就转移了,保证了内存安全和有效管理。

  3. 迭代器的使用:
    代码 s.chars().collect() 使用迭代器将字符串转换为字符向量。Rust 中的迭代器是一种高效处理集合数据的工具,支持多种操作,如映射、过滤等,此处用于字符转换。

  4. 向量处理:
    代码定义了一个向量 char_s 存储字符。Rust 中的向量(Vec)是一个动态数组,可以高效地增长和缩短,非常适合用于存储未知数量的元素。

  5. 借用与可变性:
    let mut char_s 指出 char_s 是一个可变借用,意味着可以修改其中的元素。Rust 通过可变性控制来提供更细粒度的内存管理。

  6. 遍历与条件判断:
    循环 for i in 0..n / 2 演示了 Rust 的遍历机制,其中使用范围表达式进行半长度遍历。结合条件判断,实现了字符间的比较和相应的替换逻辑。

  7. 模式匹配与替换:
    通过比较 leftright 字符,进行条件替换。这种模式匹配是 Rust 中强大的控制流工具之一,使代码更加清晰和健壯。

  8. 结果的构建:
    最后,char_s.into_iter().collect() 将修改后的字符向量重新组装成一个字符串。这体现了 Rust 的迭代器和集合框架的灵活性和强大功能。

结论

通过上述代码实现,我们可以看到,不同编程语言在处理字符串和字符的方式上有所不同,但核心算法思想是一致的。这个问题通过简单的字符比较和替换,就能够有效地实现回文串的转换,并保证字典序最小。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值