rust实现最长回文串

430 阅读3分钟

这篇文章是rust解决算法问题的第七篇,感兴趣的掘友可以去jibinbin 的个人主页 - 动态 - 掘金 (juejin.cn)查看其他文章,话不多说,直接进入正题。

image.png 409. 最长回文串 - 力扣(LeetCode) (leetcode-cn.com)也是一道难度为简单的问题,下午的时候实现了js版本,晚上按照思路搞定了rust版本。

实现思路

这个问题我的思路比较简单,回文串的话,个数可能为奇数,比如“aba”,也可能为偶数,比如“aabb”,所以要想得到最长的回文串,一定是特定条件下最大次数的累计。首先利用hashmap存储下来每个字符出现的次数,对出现次数进行从大到小的排序。之后遍历数组,如果出现次数大于1且为偶数,则直接加上该次数;如果出现次数大于1且为奇数,则直接加上该次数并减1至于为什么要减一,原因是如果现在直接加上该次数,后面可能出现的奇数都无法添加,导致不是最长的)。最后判断现在最大回文串的长度是否小于字符串的长度,如果是则证明肯定有字母出现次数为奇数次,再判断其是否为偶数,如果是则说明还可以再添加一个字母,否则不能添加。

js版本

   var longestPalindrome = function(s) {
         let map = new Map();
         let sum = 0;

         for(let i = 0;i < s.length;i++){
             if(map.has(s[i])){
                 map.set(s[i],map.get(s[i]) + 1);
             }else{
                 map.set(s[i],1);
             }
         }

         let arr = [...map.values()].sort(function(a,b){
             return b-a;
         });

         for(let i = 0;i < arr.length;i++){
             if(arr[i] > 1){
                if(arr[i] % 2 != 0){
                    sum += arr[i] - 1;
                }else{
                    sum += arr[i];
                }
             }
         }

         if(sum < s.length && sum % 2 == 0){
             sum += 1;
         }

         return sum;
};

rust版本

use std::collections::HashMap;
impl Solution {
    pub fn longest_palindrome(s: String) -> i32 {
        let mut nums = HashMap::new();
        let mut vec = vec![];
        let mut sum = 0;
        
        for item in s.chars(){
            let count = nums.entry(item).or_insert(0);
            *count += 1;
        }
        
        for (_key,value) in nums{
            vec.push(value);
        }
        
        vec.sort();  // 想要了解排序的掘友可以查看文章末尾的第二个资料
        vec.reverse();
        
        for item in &vec{
            if *item > 1 {
                if item % 2 == 0{
                    sum += item;
                }else{
                    sum += item - 1;
                }
            }
        }
        
        if sum < s.len() && sum % 2 == 0 {
            sum += 1;
        }
        
        sum as i32
    }
}

image.png

问题以及解决思路

在写rust版本的解法时,有统计字母出现次数这一步骤,想想也是很简单的嘛,判断哈希映射中是否有该键,如果有就更新其对应的值,否则插入相应的键值对。可是我却遇到了一点警告。

    if nums.contains_key(&item){
        match nums.get(&item){
            Some(val) => {
                nums.insert(item,val + 1);
            }
            
            None => {
                
            }
        }
    }else{
        nums.insert(item,1);
    }

image.png

通过查阅资料,我解锁了两种解决办法:

第一种

使用hashmap的新的api,在哈希映射中存储键和关联值 - Rust 程序设计语言 简体中文版 (kaisery.github.io),这里有具体的例子,放一下截图,感兴趣的掘友可以点击链接阅读文章

image.png

第二种

根据警告的原因和下图得知, image.png val应该是不可变的,而我为了更新出现次数,进行了加一操作,导致了这个问题,那么有没有一种方法能够返回可变的引用呢?很快,我发现了HashMap in std::collections - get_mut。然后,我将get改为了get_mut,在我以为万事大吉的时候,报错了(emmmmm)。

image.png

错误的原因也很直接,不能在同一时间多次将其作为可变变量借用。这个问题,我之前也遇到过,在rust实现接雨水 - 掘金 (juejin.cn)这篇博客里面解释过原因以及解决思路,想要了解的掘友可以点击上方链接查看,也可以查看官方文档的解释引用与借用 - Rust 程序设计语言 简体中文版 (kaisery.github.io)

知道了错误的原因,解决就很容易了,同一时间不能多次将其作为可变变量借用,那我在第二次借用之前用一次不就行了,顺利通过leetcode

image.png

查阅资料

Rust程序设计语言

Rust Cookbook 中文版

HashMap in std::collections - Rust (rust-lang.org)

结语

如果您在阅读的过程中,发现了问题或者有更好的想法,欢迎留言,感谢!!!