rust原地复活_rustTest: 个人Rust语言学习项目;翻译官方文档以及使用rust在LeetCode刷题的记录...

链表相加 addListNode(LeetCode)

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

输出:7 -> 0 -> 8

原因:342 + 465 = 807

// Definition for singly-linked list.

// #[derive(PartialEq, Eq, Clone, Debug)]

// pub struct ListNode {

// pub val: i32,

// pub next: Option>

// }

//

// impl ListNode {

// #[inline]

// fn new(val: i32) -> Self {

// ListNode {

// next: None,

// val

// }

// }

// }

impl Solution {

pub fn add_two_numbers(l1: Option>, l2: Option>) -> Option> {

}

}

查找不重复的字符 uniqueChar

从给定的字符串中查找给定字符出现的次数,判断次数是否唯一

测试字符串slice

slice字符串时带等号和不带的区别

由于算法相关的问题都是直接网上提交运行,不再单独建立项目

寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]

nums2 = [2]

则中位数是 2.0

示例 2:

nums1 = [1, 2]

nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

我的解法(不清楚复杂度的问题,过了,但是不知道是否符合复杂度要求)

impl Solution {

pub fn find_median_sorted_arrays(nums1: Vec, nums2: Vec) -> f64 {

let a=nums1.len();

let b=nums2.len();

let l= if a>b{a}else{b};

let mut v: Vec = Vec::new();

for i in (0..l){

if let Some(n)=nums1.get(i){

v.push(*n);

if let Some(m)=nums2.get(i){

v.push(*m);

}

}else{

if let Some(m)=nums2.get(i){

v.push(*m);

}

}

}

v.sort();

let ll=v.len();

let mut f:f64=0.0;

if(ll%2==0){

f=((v[v.len()/2-1] as f64)+(v[v.len()/2] as f64))/2.0;

}

else{

f=v[(v.len()-1)/2] as f64

}

f

}

}

运行时间为0的大神解法

use std::mem;

impl Solution {

pub fn find_median_sorted_arrays(nums1: Vec, nums2: Vec) -> f64 {

let (mut a , mut b) = (&nums1, &nums2);

let (mut m, mut n) = (a.len(), b.len());

if m > n {

mem::swap(&mut a, &mut b);

mem::swap(&mut m, &mut n);

}

let (mut imin, mut imax, halflen) = (0, m, (m+n+1)/2);

while imin <= imax{

let i = (imin + imax) / 2;

let j = halflen - i;

if i < imax && b[j-1] > a[i] {

imin = i + 1;

}else if i > imin && a[i -1] > b[j] {

imax = i - 1;

}else{

let (maxleft, minright);

if i == 0 {

maxleft = b[j-1];

}else if j == 0 {

maxleft = a[i-1];

}else{

maxleft = a[i-1].max(b[j-1]);

}

if(m + n) % 2 == 1{

return maxleft as f64;

}

if i == m {

minright = b[j];

}else if j == n {

minright = a[i];

}else{

minright = b[j].min(a[i]);

}

return (maxleft + minright) as f64 / 2.0 ;

}

}

return 0.0;

}

}

最长回文串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"

输出: "bab"

注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"

输出: "bb"

分析:

这个问题难度定位为中等,我倒是觉得比一般的困难还要麻烦,也可能是不熟悉RUST的原因。情况分析倒是很快出来了,程序一直跑不通,前后折腾了几个小时。

后面查资料发现了一个相当NB的马拉车算法,没详细看,感觉有点麻烦。等有时间再去肝一下。

没有系统的学过算法,按照数学分类的方式来的:

长度为0或1,直接返回

长度为2,判断是否相同,相同则直接返回

长度大于2时,先判断0,1是否相同,是的话初始串长为2,串头为0

这样的好处是对每一个字符,只需要获取已自身为中心和(自身+身后)为中心的回文串最大长度,否则加上(自身+身前)为中心的话,就会有重复操作

从1开始循环,依次获取以每个字符本身 以及 (自身+身后)为中心查找最长的回文串,记录其中最长的串长度和串头

我的代码,耗时8ms,内存2.1M

impl Solution {

pub fn longest_palindrome(s: String) -> String {

if(s.len()<2){

return s;

}

let mut ss:Vec=Vec::new();

for c in s.chars(){

ss.push(c as i32);

}

let len:usize=s.len() as usize;

//最大长度,最小为1

let mut max=1;

let mut b=0;

//前2个为相同的情况

if(s[0..1]==s[1..2]){

max=2;

b=0;

}

//从第二个开始,做i为中心和[i,i+1]为中心查找

for i in (1..len){

let mut j:usize=i as usize;

let mut k:usize=i as usize;

let mut l=0;

let mut p:usize=i as usize;

let mut q:usize=i as usize;

let mut m:usize=0;

//已自身为中心

j-=1;

k+=1;

while(j>=0&&k<=(len-1)){

if(&ss[j]==&ss[k]){

if(j==0||k==len-1){

l=2*(m as i32+1)+1;

m=0;

if(l>max as i32){max=l as usize;b=j;}

break;

}

m+=1;

j-=1;

k+=1;

}else{

l=2*(m as i32+1)-1;

m=0;

if(l>max as i32){max=l as usize;b=j+1;}

break;

}

}

//已自身和后一个为中心

q+=1;

while(p>=0&&q<=(len-1)){

if(&ss[p]==&ss[q]){

if(p==0||q==len-1){

l=2*(i as i32-p as i32+1);

if(l>max as i32){max=l as usize;b=p;}

break;

}

m+=1;

p-=1;

q+=1;

}else{

l=2*(m as i32);

if(l>max as i32){max=l as usize;b=p+1;}

break;

}

}

}

(&s[b..(b+max)]).to_string()

}

}

大神的代码 0ms,马拉车算法

impl Solution {

pub fn longest_palindrome(s: String) -> String {

let mut max_sub_str = "".to_string();

if s.len() < 1 {

return max_sub_str;

}

let mut str_ary = vec!['#'];

for c in s.chars(){

str_ary.push(c);

str_ary.push('#');

}

let str_ary_len = str_ary.len() as i32;

let mut radius = vec![0;str_ary_len as usize];

let (mut r, mut c , mut max) = (-1, -1, 0);

for i in 0..str_ary_len {

let mut k = if r > i {

radius[ (2 * c - i) as usize].min(r - i + 1)

}else{

1

};

while i + k < str_ary_len && i - k > -1 && str_ary[(i - k) as usize] == str_ary[(i + k) as usize]{

k += 1;

}

if i + k > r {

r = i + k - 1;

c = i;

}

max = max.max(k);

radius[i as usize] = k;

}

for (key, &val) in radius.iter().enumerate() {

if val == max {

max_sub_str = str_ary[key-(max as usize -1)..key+max as usize].iter()

.filter(|&x| *x != '#').collect::();

}

}

max_sub_str

}

}

大神的代码1 4ms

impl Solution {

pub fn longest_palindrome(s: String) -> String {

let mut max_length = 0;

let mut palindrome :String = String::from("");

let bytes = s.as_bytes();

let mut i = 0;

while i < bytes.len() as i32 - max_length {

let mut j:i32 = i.clone();

let mut k:i32 = i.clone();

let mut palindrome_size1 : i32 = 0;

let mut palindrome_size2 : i32 = 0;

while j >= 0 && k < s.len() as i32 && bytes[j as usize] == bytes[k as usize] {

palindrome_size1 += 1;

j -=1;

k +=1;

}

j = i.clone();

k = i.clone() + 1;

while j >= 0 && k < s.len() as i32 && bytes[j as usize] == bytes[k as usize] {

palindrome_size2 += 1;

j -=1;

k +=1;

}

if max_length < palindrome_size1 && palindrome_size1 > palindrome_size2 ||

max_length == palindrome_size1 && palindrome_size1 > palindrome_size2 && palindrome.len() as i32 % 2 != 0{

palindrome = String::from(&s[(i+1-palindrome_size1) as usize .. (i+palindrome_size1) as usize]);

max_length = palindrome_size1;

} else if max_length <= palindrome_size2 && palindrome_size2 >= palindrome_size1{

palindrome = String::from(&s[(i+1-palindrome_size2) as usize .. (i+1+palindrome_size2) as usize]);

max_length = palindrome_size2;

}

i += 1;

}

palindrome

}

}

整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123

输出: 321

示例 2:

输入: -123

输出: -321

示例 3:

输入: 120

输出: 21

注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

没想到什么好方法,直接用f64开始蛮干

我的代码

impl Solution {

pub fn reverse(x: i32) -> i32 {

let mut n:f64=0.0;

let mut y=x;

let mut t=0;

let mut q=1;

let mut v= vec![];

while (y/10)!=0 {

v.push(y%10);

y=y/10;

t+=1;

q*=10;

}

v.push(y);

for i in (0..=t){

n += (v[i] as f64) * q as f64;

q/=10;

t-=1;

}

if(n>(2147483647 as f64)||n

0

}else{

n as i32

}

}

}

没发现大神代码,估计太简单,大神不屑出手

字符串转数字(atoi)

请你来实现一个 atoi 函数,使其能将字符串转换成整数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

示例 1:

输入: "42"

输出: 42

示例 2:

输入: " -42"

输出: -42

解释: 第一个非空白字符为 '-', 它是一个负号。

我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

示例 3:

输入: "4193 with words"

输出: 4193

解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。

示例 4:

输入: "words and 987"

输出: 0

解释: 第一个非空字符是 'w', 但它不是数字或正、负号。

因此无法执行有效的转换。

示例 5:

输入: "-91283472332"

输出: -2147483648

解释: 数字 "-91283472332" 超过 32 位有符号整数范围。

因此返回 INT_MIN (−231) 。

我的代码:0 ms 1.9M

impl Solution {

pub fn my_atoi(str: String) -> i32 {

let s=str.trim();

let mut n:f64=0.0;

let mut v:Vec=Vec::new();

let mut k=0;

let mut t=0;

if s.is_empty(){

return 0;

}

let h:char=s.as_bytes()[0] as char;

if !h.is_numeric() && h!='-'&& h!='+'{

return 0;

}else if (h=='-'){

k=-1;

}else if (h=='+'){

k=1;

}

let mut len:f64=0.1;

for c in s.chars(){

match c{

'0'...'9'=>{

len*=10 as f64;

v.push(c as u8);

},

'-'=>if k==-1&& t==0{

t=1;

}else{

t=2;

},

'+'=>if k==1&& t==0{

t=1;

}else{

t=2;

},

_=>{break;}

}

if(t>1){

break;

}

}

if k==0{k=1;}

for i in &v{

n+= (*i-48) as f64 * len;

len /=10.0;

}

if(k==1&&n>2147483647 as f64){

2147483647

}else if(k==-1&&n>2147483647 as f64){

-2147483648

}else{

(n*k as f64) as i32

}

}

}

大神代码:

impl Solution {

pub fn my_atoi(s: String) -> i32 {

let mut result = 0i32;

let mut iter = s.chars()

.skip_while(|c| c.is_whitespace())

.peekable();

let sign = match iter.peek() {

Some('-') => {iter.next();-1},

Some('+') => {iter.next();1},

Some(c) if c.is_ascii_digit() => 1,

_ => return 0,

};

for c in iter {

if c.is_ascii_digit() {

let d = c.to_digit(10).unwrap() as i32;

result = result.saturating_mul(10)

.saturating_add(sign*d);

} else {

break

}

}

result

}

}

三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:

[

[-1, 0, 1],

[-1, -1, 2]

]

这个题题库给出的难度等级是中等,我感觉比不少困难的题目还要难,感受到了智商被碾压的痛苦...

思路一:

转换为两数之和,再和第三个数匹配;最后去重

哦豁~超时了

代码(比较垃圾,仅为实现功能,未考虑优化):

impl Solution {

pub fn three_sum(nums: Vec) -> Vec> {

let mut vv:Vec>=vec![];

let mut s=String::new();

let len=nums.len();

if len<3{ return vv;}

let mut vt:Vec=vec![];

let mut i=0;

let mut m=0;

let mut n=0;

while i

m=nums[i];

let mut j=i+1;

while j

n=nums[j];

if m>n{

vt.push((n,m,i as i32,0-m-n,j as i32));

}else{

vt.push((m,n,i as i32,0-m-n,j as i32));

}

j+=1;

}

//println!("{:?}",vt);

i+=1;

}

//println!("{:?}",vt);

for t in &vt{

let index=t.2;

let index1=t.4;

let x=t.0;

let y=t.1;

let z=t.3;

for j in(0..len){

if j as i32!=index && j as i32!=index1&& nums[j]==z{

let mut ss= String::new();

if(z

ss= format!("({}{}{})",z,x,y);

}else if(z>y){

ss= format!("({}{}{})",x,y,z);

}else{

ss= format!("({}{}{})",x,z,y);

}

if(s.find(&ss)==None){

s.push_str(&ss);

vv.push([t.0,t.1,t.3].to_vec());

}

break;

}

}

}

vv

}

}

后面有折腾了几个小时优化,还是不行,感觉此路不通,换思路

思路二 直接循环:

排序

开始循环:

可行,耗时768ms,内存3.3M,获取可变vec的部分应该有方法减少耗时(这样产生新的vec丑的没道理)

impl Solution {

pub fn three_sum(nums: Vec) -> Vec> {

let mut vn:Vec=Vec::new();

let mut vv:Vec>=vec![];

if nums.len()<3{ return vv;}

//vn=nums; 查到的新方法,或者直接使用

// let mut vn=nums;

for it in &nums{

vn.push(*it);

}

//使用不稳定排序sort_unstable(),这个通常比sort()要快点

vn.sort_unstable();

let l=vn.len();

//println!("vn:{:?}",vn);

//用来记录第一个数的值,防止连续多个相同的x产生重复

let mut key=-2147483648;

//用来记录第二个数的值,防止连续多个相同的x产生重复

let mut kkk=-2147483648;

for mut i in (0..l-2){

let mut k=0;

let mut x=vn[i];

if x==key{

i+=1;

continue;

}else{

key=x;

}

let mut j=i+1;

//最小值大于0,结束循环

if x>0{ break;}

let mut y=0;

let mut z=0;

while j

//println!("jjj,{},{},{},y-->{}",i,j,k,vn[j]);

y=vn[j];

if y==kkk{

j+=1;

continue;

}else{

kkk=y;

}

z=0-x-y;

k=j+1;

// k部分的循环可以用下面的3行代替,但是时间会增加

//if vn[k..l].contains(&z){

// vv.push([x,y,z].to_vec());

//}

while(k

// println!("kkk,{},{},{}",i,j,k);

let mut p=vn[k];

if p

k+=1;

}else if p==z{

//println!("vv.push:{:?},{},{},{}",vv,i,j,k);

vv.push([x,y,z].to_vec());

break;

}else{

break;

}

}

j+=1;

}

//println!("vv:{:?},{},{},{}",vv,i,j,k);

i+=1;

}

vv

}

}

大神代码(双指针) 20ms,4.5M:

impl Solution {

pub fn three_sum(nums: Vec) -> Vec> {

let nums_len = nums.len();

if nums_len < 3 {

return vec![];

}

let mut nums = nums;

nums.sort();

let mut result: Vec> = vec![];

for i in 0..nums_len {

if nums[i] > 0 {

break;

}

if i > 0 && nums[i] == nums[i - 1] {

continue;

}

let mut l = i + 1;

let mut r = nums_len - 1;

while l < r {

let sum = nums[i] + nums[l] + nums[r];

if sum == 0 {

result.push(vec![nums[i], nums[l], nums[r]]);

while l < r && nums[l] == nums[l + 1] {

l += 1;

}

while l < r && nums[r] == nums[r - 1] {

r -= 1;

}

l += 1;

r -= 1;

} else if sum > 0 {

r -= 1;

} else {

l += 1;

}

}

}

return result;

}

}

(之前的都是双指针)96ms 1.8M

impl Solution {

pub fn three_sum(mut nums: Vec) -> Vec> {

let mut ret = Vec::new();

if nums.len() < 3 {

return ret;

}

nums.sort();

for i in 0..nums.len()-2 {

if i == 0 || nums[i] != nums[i-1] {

for j in i+1..nums.len()-1 {

if j == i+1 || nums[j] != nums[j-1] {

if let Ok(p) = &nums[j+1..].binary_search(&(-nums[i]-nums[j])) {

ret.push(vec![nums[i], nums[j], nums[j+1+p]]);

}

}

}

}

}

ret

}

}

大神代码(按思路一实现)152ms 0.9M:

impl Solution {

pub fn three_sum(nums: Vec) -> Vec> {

let mut counter = std::collections::HashMap::new();

for &x in &nums {

*counter.entry(x).or_insert(0) += 1;

}

let mut keys: Vec = counter.keys().cloned().collect();

keys.sort_unstable();

let mut ans: Vec> = vec![];

for i in 0..keys.len() {

for j in i..keys.len() {

let (a, b) = (keys[i], keys[j]);

let c = -(a + b);

if ! counter.contains_key(&c) {

continue;

}

if a == b && b == c && counter[&a] >= 3 {

ans.push(vec![a, b, c]);

} else if a == b && b != c && counter[&a] >= 2 {

ans.push(vec![a, b, c]);

} else if a < b && b < c {

ans.push(vec![a, b, c]);

}

}

}

ans

}

}

最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

思路:

其实和上面的三数之和类似,最快的应该还是双指针,但我还是试了一下爆破:32ms 2M

impl Solution {

pub fn three_sum_closest(nums: Vec, target: i32) -> i32 {

let len=nums.len();

if len <3{

let mut n=0;

for i in &nums{

n+=*i;

}

return n;

}

let mut nums=nums;

nums.sort_unstable();

let mut sum=nums[0]+nums[1]+nums[2];

let mut c=(sum-target).abs();

//println!("nums:{:?},sum:{},c:{}",nums,sum,c);

for mut i in 0..len-2{

let mut j=i+1;

while j

let mut k=j+1;

while k

let mut s=nums[i]+nums[j]+nums[k];

if s==target{

return target;

}

let mut cc=(s-target).abs();

if cc<=c{ c=cc; sum=s;}

k+=1;

}

j+=1;

}

i+=1;

}

sum

}

}

双指针 0ms 1.9M

impl Solution {

pub fn three_sum_closest(mut nums: Vec, target: i32) -> i32 {

let len = nums.len();

if len < 3 {

let mut n=0;

for i in &nums{

n+=*i;

}

return n;

}

nums.sort_unstable();

let mut sum = nums[0]+nums[1]+nums[2];

let mut c = (sum-target).abs();

for i in 0..len {

if i>0 && nums[i-1] > target {

break;

}

let mut l = i+1;

let mut r = len-1;

while l < r {

let s = nums[i]+nums[l]+nums[r];

let cc = (s-target).abs();

if cc < c {

if cc == 0 {

return s;

}

c = cc;

sum = s;

}

if s > target {

r-=1;

} else {

l+=1;

}

}

}

sum

}

}

其它算法(大神算法,没细看) 4ms,24.14M:

impl Solution {

pub fn three_sum_closest(mut nums: Vec, target: i32) -> i32 {

nums.sort();

let mut ret = 0;

let mut d = i32::max_value();

for i in 0..nums.len()-2 {

for j in i+1..nums.len()-1 {

let t = target - nums[i] - nums[j];

let s = &nums[j+1..];

match s.binary_search(&t) {

Ok(_) => {

return target;

},

Err(k) => {

if k < s.len() && (t - s[k]).abs() < d {

ret = nums[i] + nums[j] + s[k];

d = (ret - target).abs();

}

if k > 0 && (t - s[k-1]).abs() < d {

ret = nums[i] + nums[j] + s[k-1];

d = (ret - target).abs();

}

},

}

}

}

ret

}

}

有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。

左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

示例 1:

输入: "()"

输出: true

示例 2:

输入: "()[]{}"

输出: true

示例 3:

输入: "(]"

输出: false

示例 4:

输入: "([)]"

输出: false

示例 5:

输入: "{[]}"

输出: true

思路:直接push pop操作即可 0ms,2M

impl Solution {

pub fn is_valid(s: String) -> bool {

if s.len()%2==1{

return false;

}

let mut ss=String::new();

for c in s.chars(){

match c{

')'=>{

if ss.pop()!=Some('('){

return false;

}

},

']'=>{

if ss.pop()!=Some('['){

return false;

}

},

'}'=>{

if ss.pop()!=Some('{'){

return false;

}

},

_=>ss.push(c)

};

}

ss.is_empty()

}

}

删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝

int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。

// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。

for (int i = 0; i < len; i++) {

print(nums[i]);

}

思路一: 找出重复项,删除再返回长度 8ms,2.2M

impl Solution {

pub fn remove_duplicates(nums: &mut Vec) -> i32 {

let mut len=nums.len();

if len<2{

return len as i32;

}

let mut n=nums[0];

let mut v:Vec=vec![];

for mut i in 1..len{

println!("i:{} v:{:?}",i,v);

if nums[i]==n{

len-=1;

v.push(i as i32);

}else{

n=nums[i];

i+=1;

}

}

for mut j in 0..v.len(){

//println!("i:{} nums:{:?},v[j]:{}",j,nums,v[j]);

nums.remove(v[j] as usize-j);

}

len as i32

}

}

优化一下,缩短代码:

impl Solution {

pub fn remove_duplicates(nums: &mut Vec) -> i32 {

let mut len=nums.len();

if len<2{

return len as i32;

}

let mut n=nums[0];

let mut k=0;

for mut i in 1..len{

i= i-k;

//println!("i:{} nums:{:?}",i,nums);

if nums[i]==n{

nums.remove(i);

len-=1;

k+=1;

}else{

n=nums[i];

i+=1;

}

}

len as i32

}

}

不删,直接修改并返回长度 0ms,2.2M

impl Solution {

pub fn remove_duplicates(nums: &mut Vec) -> i32 {

let mut len=nums.len();

if len<2{

return len as i32;

}

let mut n=nums[0];

let mut k=0;

for mut i in 1..len{

//println!("i:{} nums:{:?}",i,nums);

if nums[i]==n{

len-=1;

}else{

n=nums[i];

k+=1;

nums[k]=n;

}

}

len as i32

}

}

搜索旋转排序数组

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0

输出: 4

示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3

输出: -1

分析:不要求时间复杂度的话,直接contains即可,这里用二分查找,不清楚是否符合要求

代码 0ms,2M

impl Solution {

pub fn search(nums: Vec, target: i32) -> i32 {

let len=nums.len();

if len<1{

return -1;

}

if len==1 && nums[0]==target{

return 0;

}else if len==1 && nums[0]!=target{

return -1;

}

let mut l=0;

let mut r=len-1;

while l<=r{

if target==nums[l]{

return l as i32;

}

if target==nums[r]{

return r as i32;

}

l+=1;

r-=1;

}

-1

}

}

字符串相乘

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

示例 1:

输入: num1 = "2", num2 = "3"

输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"

输出: "56088"

说明:

num1 和 num2 的长度小于110。

num1 和 num2 只包含数字 0-9。

num1 和 num2 均不以零开头,除非是数字 0 本身。

不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理

思路:

不能用大数或转整数,考虑将乘法转换为加法计算

循环获取各位相乘的值和位数(尾部0的个数)

记入以位数为key值为value的HashSet

获取各种位数的值和进位值,生成字符串

代码 16ms 1.9M

use std::collections::HashMap;

impl Solution {

pub fn multiply(num1: String, num2: String) -> String {

if &num1=="0"||&num2=="0"{

return String::from("0");

}

if &num1=="1"{

return num2;

}

if &num2=="1"{

return num1;

}

let mut l1=num1.len();

let mut l2=num2.len();

let mut l=l1+l2-2;

let mut n1=num1.as_bytes();

let mut n2=num2.as_bytes();

let mut mp = HashMap::new();

for mut i in 0..l1{

for mut j in 0..l2{

let mut m=(n1[i] as i32-48)*(n2[j] as i32-48);

let mut n=(l-i-j) as i32;

if mp.contains_key(&n){

let p=mp.get(&n).unwrap()+m;

mp.insert(n,p);

}else{

mp.insert(n,m);

}

}

}

Self::check(mp)

}

fn check(mut mp:HashMap)->String{

let mut s=String::new();

let mut key=0;

for i in 0..mp.len(){

let mut m=mp.get(&(i as i32)).unwrap()+key;

s = (m%10).to_string()+&s;

key=m/10;

}

if key>0{

s = key.to_string()+&s;

}

s

}

}

大神算法 0ms 80M

直接按照乘法计算

impl Solution {

pub fn multiply(num1: String, num2: String) -> String {

if num1 == "0" || num2 == "0" {

return String::from("0");

}

let num1 = num1.as_bytes();

let num2 = num2.as_bytes();

let mut rst = vec!['0' as u8; num1.len() + num2.len() + 1];

let mut cur = 0;

for idx1 in (0..num1.len()).rev() {

let cur1 = num1[idx1] - '0' as u8;

let mut rst_cur = rst.len() - 1 - cur;

for idx2 in (0..num2.len()).rev() {

let cur2 = num2[idx2] - '0' as u8;

let mul = cur2 * cur1 + rst[rst_cur] - '0' as u8;

rst[rst_cur] = mul % 10 + '0' as u8;

rst[rst_cur - 1] = rst[rst_cur - 1] - ('0' as u8) + mul / 10 + '0' as u8;

rst_cur -= 1;

}

cur += 1;

}

for idx in 0..rst.len() {

if rst[idx] != '0' as u8 {

cur = idx;

break;

}

}

let rst = String::from_utf8(rst).unwrap();

rst[cur..].to_string()

}

}

全排列

给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]

输出:

[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

]

脑子不够用,时间来凑...

分别以序列中每一个元素为头处理

去头

去头后的新序列获取不同顺序的新序列组

对新序列组中的每一个序列重复上面的去头和获取序列组步骤

若新序列长度为2,返回本身和交换位置的序列

对每一个返回的序列加头

对返回的每一个序列加头,重复值不添加至返回序列组

对将返回序列组中的序列加入到返回值序列组

需要学习一下,知道用递归可以写出漂亮的代码,可是就是不知道该怎么用...

代码 8ms 2.1M

impl Solution {

pub fn permute(nums: Vec) -> Vec> {

let mut v:Vec>=vec![];

let mut num=vec![];

num.extend_from_slice(&nums);

let len=nums.len();

if len<2{

v.push(nums);

return v;

}else if len==2{

let p=nums[0];

let q=nums[1];

v.push(vec![p,q]);

v.push(vec![q,p]);

return v;

}

else{

for i in 0..len{

let mut num=vec![];

let mut vs:Vec>=vec![];

num.extend_from_slice(&nums);

vs = Self::check(i,&num);

for m in &vs{

v.push(m.to_vec());

}

}

/*let mut num=vec![];

let mut vs:Vec>=vec![];

num.extend_from_slice(&nums);

vs = Self::check(3,num);

for m in &vs{

v.push(m.to_vec());

} */

v

}

}

fn check(i:usize,nums:& Vec)->Vec>{

let mut v:Vec>=vec![];

let len=nums.len();

let mut k=vec![];

k.extend_from_slice(&nums);

let key=k[i];

if len>2{

k.remove(i);

let mut pp:Vec>=vec![];

let mut ps:Vec>=vec![];

let mut k0=vec![];

k0.extend_from_slice(&k);

ps.push(k0);

for j in 1..k.len(){

for m in 0..k.len()-1{

let mut kk=vec![];

kk.extend_from_slice(&k);

if j!=m{

kk.swap(m,j);

ps.push(kk);

}

}

}

//println!("i-->{},ps:{:?}",i,ps);

for ss in &ps{

let mut vv:Vec>=vec![];

vv=Self::check(0,&ss.to_vec());

for p in &vv{

let mut q:Vec=p.to_vec();

q.insert(0,key);

if !pp.contains(&q){

pp.push(q);

}

}

}

//println!("i-->{},pp:{:?}",i,pp);

v=pp;

}

else if len==2{

let mut kk=vec![];

kk.extend_from_slice(&k);

v.push(k);

kk.swap(0,1);

v.push(kk);

}

// println!("v------->{:?}",v);

v

}

}

稍作修改,优化部分无效代码 4ms,2.2M

impl Solution {

pub fn permute(nums: Vec) -> Vec> {

let mut v=vec![];

let len=nums.len();

if len<2{

v.push(nums);

}else if len==2{

let p=nums[0];

let q=nums[1];

v.push(vec![p,q]);

v.push(vec![q,p]);

}

else{

for i in 0..len{

let mut vs=vec![];

vs = Self::check(i,&nums);

for m in &vs{

v.push(m.to_vec());

}

}

}

v

}

fn check(i:usize,nums:& Vec)->Vec>{

let mut v=vec![];

let len=nums.len();

let mut k=vec![];

k.extend_from_slice(&nums);

let key=k[i];

if len>2{

k.remove(i);

let mut pp=vec![];

let mut ps=vec![];

for j in 1..k.len(){

for m in 0..k.len()-1{

let mut kk=vec![];

kk.extend_from_slice(&k);

if j!=m{

kk.swap(m,j);

ps.push(kk);

}

}

}

//println!("i-->{},ps:{:?}",i,ps);

for ss in &ps{

let mut vv=vec![];

vv=Self::check(0,&ss.to_vec());

for p in &vv{

let mut q=p.to_vec();

q.insert(0,key);

if !pp.contains(&q){

pp.push(q);

}

}

}

//println!("i-->{},pp:{:?}",i,pp);

v=pp;

}

else if len==2{

let mut kk=vec![];

kk.extend_from_slice(&k);

v.push(k);

kk.swap(0,1);

v.push(kk);

}

// println!("v------->{:?}",v);

v

}

}

大神代码 0ms 93.10M 直接递归,确实漂亮

impl Solution {

pub fn permute(nums: Vec) -> Vec> {

let mut ret = vec![];

let mut nums = nums;

Self::traverse(0, &mut nums, &mut ret);

ret

}

fn traverse(first: usize, cur: &mut Vec, ret: &mut Vec>) {

if first == cur.len() {

ret.push(cur.to_owned());

}

for i in first..cur.len() {

cur.swap(i, first);

Self::traverse(first + 1, cur, ret);

cur.swap(i, first);

}

}

}

最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],

输出: 6

解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

进阶:

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

代码:0ms 2.2M

impl Solution {

pub fn max_sub_array(nums: Vec) -> i32 {

let mut m=nums[0];

let mut s=m;

let len=nums.len();

for i in 1..len{

let mut temp=m+nums[i];

if nums[i]>temp{

m=nums[i];

}else{

m=temp;

}

if s>m{

s=s;

}else{

s=m;

}

}

s

}

}

合并两个有序数组

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n。

你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:

输入:

nums1 = [1,2,3,0,0,0], m = 3

nums2 = [2,5,6], n = 3

输出: [1,2,2,3,5,6]

代码 0ms 2.1M

impl Solution {

pub fn merge(nums1: &mut Vec, m: i32, nums2: &mut Vec, n: i32) {

for i in 0..n as usize{

nums1[i+m as usize]=nums2[i];

}

nums1.sort();

}

}

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]

输出: 1

示例 2:

输入: [4,1,2,1,2]

输出: 4

代码 0ms 2.2M

impl Solution {

pub fn single_number(nums: Vec) -> i32 {

let mut nums=nums;

nums.sort();

if nums.len()==1{

return nums[0];

}

let mut i=0;

while i< nums.len()-2{

if nums[i]!=nums[i+1]{

return nums[i];

}else{

i+=2;

}

}

nums[i]

}

}

大神代码 0ms 82M

impl Solution {

pub fn single_number(nums: Vec) -> i32 {

let mut res = 0 as i32;

for i in &nums {

res ^= *i;

}

res

}

}

多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入: [3,2,3]

输出: 3

示例 2:

输入: [2,2,1,1,1,2,2]

输出: 2

代码 4ms 2.4M

use std::collections::HashMap;

impl Solution {

pub fn majority_element(nums: Vec) -> i32 {

let mut map = HashMap::new();

let len=nums.len()/2+1;

let mut n=nums[0];

for k in &nums {

let count = map.entry(k).or_insert(0);

*count += 1;

if(*count>=len){

n= *k;

break;

}

}

n

}

}

大神代码:0ms 58.54M

impl Solution {

pub fn majority_element(nums: Vec) -> i32 {

let mut nums = nums;

let len = nums.len();

nums.sort();

nums[len / 2]

}

}

存在重复元素

给定一个整数数组,判断是否存在重复元素。

如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

示例 1:

输入: [1,2,3,1]

输出: true

示例 2:

输入: [1,2,3,4]

输出: false

示例 3:

输入: [1,1,1,3,3,4,3,2,4,2]

输出: true

代码 4ms 5.2M 使用hashmap要慢一些

use std::collections::HashMap;

impl Solution {

pub fn contains_duplicate(nums: Vec) -> bool {

let mut map = HashMap::new();

let mut b=false;

for k in &nums {

let count = map.entry(k).or_insert(0);

*count += 1;

if(*count>1){

b=true;

break;

}

}

b

}

}

大神代码 0ms 27.78M

impl Solution {

pub fn contains_duplicate(mut nums: Vec) -> bool {

if nums.len() < 2 {

return false;

}

nums.sort();

for i in 1..nums.len() {

if nums[i] == nums[i - 1] {

return true;

}

}

false

}

}

2的幂

给定一个整数,编写一个函数来判断它是否是 2 的幂次方。

示例 1:

输入: 1

输出: true

解释: 2^0 = 1

示例 2:

输入: 16

输出: true

解释: 2^4 = 16

示例 3:

输入: 218

输出: false

代码 0ms 2M

impl Solution {

pub fn is_power_of_two(n: i32) -> bool {

if n==1{

return true;

}else if n==0{

return false;

}else if n%2==1{

return false;

}else{

return Self::is_power_of_two(n/2);

}

}

}

大神代码 0ms 2M 直接位运算返回

impl Solution {

pub fn is_power_of_two(n: i32) -> bool {

return n > 0 && 0 == ((n-1) & n);

}

}

反转字符串中的单词 III

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:

输入: "Let's take LeetCode contest"

输出: "s'teL ekat edoCteeL tsetnoc"

注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

代码 4ms 2.2M 分割->翻转->拼接->去尾部空格

impl Solution {

pub fn reverse_words(s: String) -> String {

let mut ss=String::new();

for word in s.split_whitespace() {

ss.push_str(&Self::reverse(word.to_string()));

}

ss.trim().to_string()

}

fn reverse(s:String)->String{

let mut ss=s;

unsafe {

let vec = ss.as_mut_vec();

vec.reverse();

ss=String::from_utf8(vec.to_vec()).unwrap();

ss.push(' ');

}

ss

}

}

大神代码 0ms 2.1M 直接干

impl Solution {

pub fn reverse_words(s: String) -> String {

let mut start_idx = 0;

let mut end_idx = 0;

let mut result = String::new();

let chars = s.as_bytes();

loop {

if end_idx == s.len() || chars[end_idx] == ' ' as u8 {

for idx in (start_idx..end_idx).rev() {

result.push(chars[idx] as char);

}

if end_idx != s.len() {

result.push(' ');

} else {

break;

}

start_idx = end_idx + 1;

}

end_idx += 1;

}

result

}

}

反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:

输入:["h","e","l","l","o"]

输出:["o","l","l","e","h"]

示例 2:

输入:["H","a","n","n","a","h"]

输出:["h","a","n","n","a","H"]

代码 24ms 5.3M

impl Solution {

pub fn reverse_string(s: &mut Vec) {

if s.len()>1

{

let mut r=s.len()-1;

let mut l=0;

while(l

s.swap(l,r);

l+=1;

r-=1;

}

}

}

}

其它方案:直接reverse()返回;

除自身以外数组的乘积

给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

示例:

输入: [1,2,3,4]

输出: [24,12,8,6]

说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。

进阶:

你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)

代码 4ms 3.2M

impl Solution {

pub fn product_except_self(nums: Vec) -> Vec {

let mut r:Vec=Vec::new();

let mut l:Vec=Vec::new();

let mut len=nums.len();

r.push(1);

l.push(1);

//println!("len:{}",len);

for i in 1..len{

let mut m=l[i-1]*nums[i-1];

let mut n=r[i-1]*nums[len-i];

l.push(m as i32);

r.push(n as i32);

}

//println!("l:{:?},r:{:?}",l,r);

for i in 0..len{

l[i]=l[i]*r[len-i-1];

//r.push(n as i32);

}

l

}

}

数组中的第K个最大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2

输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4

输出: 4

说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

代码 0ms 2.1M

impl Solution {

pub fn find_kth_largest(nums: Vec, k: i32) -> i32 {

let mut v=nums.clone();

let mut n=nums.len()-k as usize;

v.sort();

v[n]

}

}

大神代码 使用BinaryHeap,这个没看过文档,代码看不懂...下周把文档翻了看一下

use std::collections::BinaryHeap;

impl Solution {

pub fn find_kth_largest(nums: Vec, k: i32) -> i32 {

let mut heap = BinaryHeap::new();

for n in nums {

heap.push(n);

}

for _ in 0..k - 1 {

heap.pop();

}

*heap.peek().unwrap()

}

}

买卖股票的最佳时机 II

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [7,1,5,3,6,4]

输出: 7

解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。

随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

示例 2:

输入: [1,2,3,4,5]

输出: 4

解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。

注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。

因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:

输入: [7,6,4,3,1]

输出: 0

解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

代码 0ms 2.1M

impl Solution {

pub fn max_profit(prices: Vec) -> i32 {

let mut t=0;

if prices.is_empty(){

return 0;

}

let mut min=prices[0];

for i in &prices{

if *i>min{

t+=*i-min;

min=*i;

}

min=*i;

}

t

}

}

环形链表

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1

输出:true

解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0

输出:true

解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1

输出:false

解释:链表中没有环。

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

此问题无LeetCode无Rust选项,使用C快慢指针处理

代码 12ms 8.6M

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* struct ListNode *next;

* };

*/

bool hasCycle(struct ListNode *head) {

if( (head == NULL) || (head->next == NULL)){

return false;

}

struct ListNode* slow = head;

struct ListNode* fast = head->next;

while (slow != fast) {

if (fast == NULL || fast->next == NULL) {

return false;

}

slow = slow->next;

fast = fast->next->next;

}

return true;

}

相交的链表(C实现)

编写一个程序,找到两个单链表相交的起始节点。

如下面的两个链表:

在节点 c1 开始相交。

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3

输出:Reference of the node with value = 8

输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1

输出:Reference of the node with value = 2

输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2

输出:null

输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。

解释:这两个链表不相交,因此返回 null。

思路:找出更长的链表和长度差,从链表倒序长度相同开始的地方开始循环比较

代码 48ms,15.2M

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* struct ListNode *next;

* };

*/

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {

if(headA==NULL||headB==NULL){

return NULL;

}

struct ListNode* m = headA;

struct ListNode* n = headB;

int len=0;

int t=0;

bool b=false;

while(m->next!=NULL&&n->next!=NULL){

m=m->next;

n=n->next;

t++;

}

while(m->next!=NULL){

m=m->next;

len++;

}

while(n->next!=NULL){

n=n->next;

len++;

b=true;

}

m = headA;

n = headB;

//printf("len=%d,b=%d,t=%d",len,b,t);

if(b){

while(len>0){

n=n->next;

len--;

}

}else{

while(len>0){

m=m->next;

len--;

}

}

while(m!=n){

m=m->next;

n=n->next;

}

return m;

}

大神代码 40ms 15.2M 硬来,但是代码很漂亮

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* struct ListNode *next;

* };

*/

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {

struct ListNode *a = headA;

struct ListNode *b = headB;

while (a != b) {

a = a == NULL ? headB : a->next;

b = b == NULL ? headA : b->next;

}

return a;

}

反转链表(C实现)

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL

输出: 5->4->3->2->1->NULL

进阶:

你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

代码 4ms 7.6M 头插

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* struct ListNode *next;

* };

*/

struct ListNode* reverseList(struct ListNode* head){

if(!head){return NULL;}

struct ListNode *m = NULL;

struct ListNode *n;

while (head != NULL) {

n = head;

head = head->next;

//头插

n->next = m;

m = n;

}

return m;

}

代码 8ms 7.7M 递归

struct ListNode* reverseList(struct ListNode* head){

if(head == NULL || head->next == NULL){

return head;

}

struct ListNode* n = reverseList(head->next);

head->next->next = head;

head->next = NULL;

return n;

}

二叉搜索树的最近公共祖先(C实现)

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8

输出: 6

解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4

输出: 2

解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。

p、q 为不同节点且均存在于给定的二叉搜索树中。

分析:题目的关键在于搞清楚啥是二叉搜索树,知道了就简单,不知道就只能暴力搜索

百度百科

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

代码: 44ms 30.3M

/**

* Definition for a binary tree node.

* struct TreeNode {

* int val;

* struct TreeNode *left;

* struct TreeNode *right;

* };

*/

struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {

if(root==NULL||root==p||root==q){

return root;

}

while(root){

if(p->valval&&q->valval){

root=root->left;

}else if(p->val>root->val&&q->val>root->val){

root=root->right;

}else{

return root;

}

}

return root;

}

大神代码 使用递归 8ms

/**

* Definition for a binary tree node.

* struct TreeNode {

* int val;

* struct TreeNode *left;

* struct TreeNode *right;

* };

*/

struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {

int rv = root->val, pv = p->val, qv = q->val;

if (rv == pv || rv == qv) return root;

if ((rv < pv && rv > qv) || (rv > pv && rv < qv)) return root;

if (rv < pv) return lowestCommonAncestor(root->right, p, q);

return lowestCommonAncestor(root->left, p, q);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值