• Rust leetcode 初级算法 字符串 代码汇总


    反转字符串

    最简单的解决方法!

     s.reverse();
    

     当然也可以自己写!

     let len = s.len();
     let mut t: char;
     for i in 0..len / 2 {
     t = s[i];
     s[i] = s[len - i - 1];
     s[len - i - 1] = t;
     }

    整数反转,如果是leet 上写 在 i32前加std 例如 std::i32::MAX, 官方推荐直接i32

     if x > i32::MAX - 1 || x < i32::MIN || x == i32::MIN {
            return 0;
        }
        let mut x: i64 = x as i64;
        let mut newnum: i64 = 0;
        while x != 0 {
            newnum = newnum * 10 + x % 10 as i64;
            x /= 10;
            if newnum > i32::MAX as i64 || newnum < i32::MIN as i64 {
                return 0;
            }
        }
        return newnum as i32;

    字符串中的第一个唯一字符

    首先创建一个装下所有字母的数组,然后记录出现了几次,类似查重复,之后在迭代一下原字符串,

    如果这个字符只出现一次,就返回。第一次迭代为了记录次数,第二次迭代是保证顺序的情况下找出只出现一次的。

        if s == "" {
            return 0;
        }
        let mut index = 0;
        let mut array = vec![0; 26];
        for c in s.bytes() {
            if array[(c - 97) as usize] != 0 {
                array[(c - 97) as usize] = array[(c - 97) as usize] + 1;
                continue;
            }
            array[(c - 97) as usize] = 1;
        }
        for c in s.bytes() {
            if array[(c - 97) as usize] == 1 {
                return index;
            }
            index = index + 1;
        }
        return -1;

    有效的字母异位词

    和上一道题差不多,首先能装下字母的数组,在第一个字符串出现+1,下一个字符串出现-1,最后判断是否等于0;

    iter.zip(iter)是把两个迭代器压缩到一起,然后一起迭代,就和切两根黄瓜一样,就是并排切的意思。

        if s == t {
            return true;
        }
        if s.len() != t.len() {
            return false;
        }
        let s = s.bytes();
        let t = t.bytes();
        let mut v = vec![0; 26];
        // for _ in 0..s.len() {
        //     let st = s.next().unwrap() as usize;
        //     let vt = t.next().unwrap() as usize;
        //     v[st - 97] = v[st - 97] + 1;
        //     v[vt - 97] = v[vt - 97] - 1;
        // }
        for (a, b) in s.zip(t) {
            v[a as usize - 97] = v[a as usize - 97] + 1;
            v[b as usize - 97] = v[b as usize - 97] - 1;
        }
        for e in v.iter() {
            if *e != 0 {
                return false;
            }
        }
        return true;

    验证回文串

    什么是回文串,简单来说就是,正着读和翻过来读是一样的,就是比较下标 [i] 和 [len-i -l] 这一对下标是否相等;

    感受一下Rust的优雅!

        let chars = s
            .chars()
            .filter(|x| x.is_ascii_alphanumeric())
            .map(|x| x.to_ascii_lowercase())
            .collect::<Vec<char>>();
        for (a, b) in chars[0..(chars.len() / 2)].iter().zip(chars.iter().rev()) {
            if a != b {
                return false;
            }
        }
        true

     字符串转换整数(atoi)

    我的思路是使用match去匹配字符,有效的字符加到字符串,其中要考虑 " " +  -  0 ,这四种字符和其他字符,每当+ - 出现,另外紧接着的不是数字就结束,出现空格就结束循环,但是一旦出现 0 + - 这些字符,就要标记已经出现可以解析的字符串了,

    然后就有了下面的垃圾代码,建议,跑一些,去看看别人怎么写,下面的代码有时候是0ms 有时候是4ms。

        let mut result = String::new();
       // 这个标志位是正负号,在最后的结果会乘以这个标志位 let mut bz_fuhao
    = 0;
       // 这是开始的标志位,意味着0 + -后面可能出现可解析的字符串 let mut bz_kaishi
    = 0; for c in s.chars() { match c {
           // 首先清除空格
    ' ' => {
             // 但是开始标志位变化,在出现空格就要结束循环
    if bz_kaishi != 0 { break; } continue; }
           // 0在有效数字前是不添加到结果里的,但是0出现标志着开始收集字符了
    '0' => { if result == "" { bz_kaishi = 1; continue; } if result != "" { result.push(c); } }
           // 这就是正常收集字符
    '1'..='9' => { bz_kaishi = 1; result.push(c); }
           // 符号位出现
    '-' => {
             // 如果开始收集字符了,但是又出现 - 就要结束
    if bz_kaishi != 0 { break; }          // 收集的字符不是空出现 - 也要结束 if result != "" { break; }
             // 表示一旦收集了一个 - 号,再次出现结束循环
    if bz_fuhao != 0 { break; }
             // 收集的字符是空的时候出现 - 号 ,之后就收集
    if result == "" { bz_fuhao = -1; bz_kaishi = 1; continue; } }
            // 和减号类似
    '+' => { if bz_kaishi != 0 { break; } if result != "" { break; } if bz_fuhao != 0 { break; } if result == "" { bz_fuhao = 1; bz_kaishi = 1; continue; } }
            // 出现其他字符直接结束 _
    => break, } } // 2147483647 -2147483648
      // 如果未出现 + 要把符号位替换为1;
    if bz_fuhao == 0 { bz_fuhao = 1; }
      // 判断长度
    if result.len() > 10 && bz_fuhao == 1 { return 2147483647; } if result.len() > 10 && bz_fuhao == -1 { return -2147483648; }
      // 只要解析的时候不溢出就行 match result.parse::
    <i128>() { Ok(o) => { if o * bz_fuhao < -2147483648 { return -2147483648; } if o * bz_fuhao > 2147483647 { return 2147483647; } return (o * bz_fuhao) as i32; } Err(_) => return 0, }

    实现strStr()

    这个就是 短字符串在长字符串能滑动几下到头,简单说一下就是,一个长度为7的箱子,你有一个长度为6的小箱子,

    从头滑动,滑动一次就到头了,如果是5长度就要滑动2次就到头了,想一下有几个位置状态开始一个加上滑动的次数。

    len_h - len_n + 1 就是长字符串可以切割出来的字符。每次切掉 短字符串的长度去比较。

            if needle == ""||haystack == needle{
                return 0;
            }
            let len_h = haystack.len();
            let len_n = needle.len();
            let mut haystack = haystack;
            if len_h < len_n {
                return -1
            }
            for i in 0..len_h-len_n+1{
                if haystack.split_at(len_n).0 == needle{
                    return i as i32
                }
                haystack = haystack.split_at(1).1.into();
            }
            return -1;

    外观数列

    解析先知道什么是外观数列,然后自己看代码吧,我也迷糊。

            if  n == 1 {
                return "1".into();
            }
            let mut res = String::new();
            let str_t = Solution::count_and_say(n-1);
            let len = str_t.len();
            let mut t = 0;
            for i in 1..len+1 {
                if  i == len{
                    res.push_str(&(i - t).to_string());
                    res.push_str(str_t.get(t..t+1).unwrap());
                    return res;
                }else if str_t.get(i..i+1) != str_t.get(t..t+1){
                    res.push_str(&(i - t).to_string());
                    res.push_str(str_t.get(t..t+1).unwrap());
                    t = i;
                } 
            }
            res

    最长公共前缀

    首先声明一个结束的标志位,思路就是随便找一个字符串,最好是第一个字符串,然后迭代它,每次比较一个字符,判断和其他的字符串同位置的是否相同,

    不相同就结束,然后截取结束标志位之前的字符。注意在for循环外返回的需要加1,要不然截取不完全。

            let len  = strs.len();
            if len == 0 {
                return "".into();
            }
            if len  == 1 {
                return strs[0].clone();
            }
            let len0 = strs[0].len();
            if len0 == 0 {
                return "".into();
            }
            let mut t = 0;
            for i in 0..len0{
                    t =i;
                    let strs0t = strs[0].get(i..i+1).unwrap_or_default();
                    if strs0t == ""{
                        return strs[0].get(0..t).unwrap().into(); 
                    }
                    for j in 1..len {
                        if 0 == strs[j].len(){
                            return "".into(); 
                        }
                        let strsit = strs[j].get(i..i+1).unwrap_or_default();
                        if strs0t == ""{
                            return strs[0].get(0..t).unwrap().into(); 
                        }
                        if strs0t == strsit {
                            continue
                        }else{
                            return strs[0].get(0..t).unwrap().into(); 
                        }
                    }      
            }
            return  strs[0].get(0..t+1).unwrap().into(); 

    到这里就结束了,之前一个算法一个博客浪费空间,感觉还是和在一起好点,方便看。

  • 相关阅读:
    当开发者产生一个伟大的想法之后应该做的10件事
    PUT 还是 POST ?
    Failed to issue method call: Unit mysqld.service failed to load: No such file or directory.
    使用 Protocol Buffers 代替 JSON 的五个原因
    Java 打印堆栈的几种方法
    Eclipse调试Java的10个技巧
    如何使用命令查看系统名称?
    Feed系统架构资料收集
    dcm4chee 修改默认(0002,0013) ImplementationVersionName
    【原创】分布式之数据库和缓存双写一致性方案解析
  • 原文地址:https://www.cnblogs.com/Addoil/p/13433361.html
Copyright © 2020-2023  润新知