反转字符串
最简单的解决方法!
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();
到这里就结束了,之前一个算法一个博客浪费空间,感觉还是和在一起好点,方便看。