You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rust_basic_code/md_file/2488. 统计中位数为 K 的子数组.md

5.0 KiB

2488. 统计中位数为 K 的子数组

description:

给你一个长度为 n 的数组 nums ,该数组由从 1n不同 整数组成。另给你一个正整数 k。统计并返回 nums 中的 中位数 等于 k 的非空子数组的数目。

代码:

use std::collections::HashMap;
use std::cmp::Ordering;
fn main() {
    let nums = vec![3, 2, 1, 4, 5];
    let k = 4;

    let nums = vec![2, 3, 1];
    let k = 3;
    let res = count_subarrays2(&nums, k);
    println!(" {} ", res);
}
fn count_subarrays2(nums: &[i32], k:i32)->i32{
    // 在 nums 数组中查找元素 k 的位置,使用了 iter() 方法和 position() 方法。
    // |&x| 表示闭包接收一个参数,使用 x 来引用这个参数,而 & 表示参数是通过引用传递而不是值传递。| 符号用于表示闭包的开始和结束。
    let mut k_index = nums.iter().position(|&x| x== k).unwrap();

    let (mut ans, mut sum) = (0, 0);
    let mut counts = HashMap::new();
    counts.insert(0, 1);

    // 使用&num是为了避免拷贝数据。(i32数据)不涉及所有权。。
    for (i, &num) in nums.iter().enumerate(){
        sum += sign2(num - k);
        if i < k_index{
            *counts.entry(sum).or_insert(0) += 1;
        }else {
            let prev_0 = *counts.get(&sum).unwrap_or(&0);
            let prev_1 = *counts.get(&(sum-1)).unwrap_or(&0);
            ans += prev_0 + prev_1;
        }
    }
    for (i, num) in nums.iter().enumerate(){
        println!("i is {} ; num is {}", i, num)
    }
    ans
}

fn sign2(num:i32)->i32{
    match num.cmp(&0) {
        Ordering::Equal => 0,
        Ordering::Greater => 1,
        Ordering::Less => -1,
    }
}

fn count_subarrays(nums: &[i32], k:i32)->i32{
    let n = nums.len();
    let mut k_index:i32 = -1;

    for i in 0..n {
        if nums[i] == k{
            k_index = i as i32;
            break;
        }
    }
    // println!(" index is {} ", k_index as usize);
    let (mut ans, mut sum) = (0, 0);
    let mut counts = HashMap::new();
    counts.insert(0, 1);
    for i in 0..n {
        sum += sign(nums[i] - k);
        if i < k_index as usize{
            let count = counts.entry(sum).or_insert(0);
            *count += 1;
        }else {
            let prev0 = *counts.get(&sum).unwrap_or(&0);
            let prev1 = *counts.get(&(sum-1)).unwrap_or(&0);
            ans += prev0 + prev1;
        }
    }
    ans
}

fn sign(num:i32)->i32{
    if num == 0{
        0
    }else {
        if num > 0 { 1 } else { -1 }
    }
}


// 在 Rust 中,数组的下标访问操作符 [] 已经被实现为语言特性,对于数组和切片类型,可以直接使用下标操作符访问其元素。''

// 在 Rust 中,数组或向量的元素可以通过索引访问,无论是使用 [] 运算符还是 get() 方法。
// 当使用 [] 运算符时,Rust 会自动解引用数组或向量的引用,并将其作为指向第一个元素的指针来处理。
// 因此,无论是 for road in &roads 还是 for road in roads,在使用 road[0] 访问数组或向量的第一个元素时,都将自动解引用指向该元素的指针,返回一个 i32 类型的值。
// 这是 Rust 语言的自动解引用功能的一部分,它使得代码更加简洁和易读。

for (i, &num) in nums.iter().enumerate() 使用&num的好处:

使用&num是为了避免拷贝数据。当使用迭代是的,这里只涉及空间占用。使用&numnum更好,因为在这里我们只是需要引用num的值,而不需要所有权。

使用引用可以减少副本的创建和内存占用。此外,当nums向量中的元素是较大的结构体或对象时,使用引用可能会更显著地减少内存使用和复制操作。器nums.iter()进行遍历时,每个元素都是被不可变地借用了,这意味着在遍历过程中不能修改这个元素。

nums.iter().position(|&x| x== k).unwrap() 作用:

nums 数组中查找元素 k 的位置,使用了 iter() 方法和 position() 方法。其中 iter() 方法将数组转换成迭代器,position() 方法会在迭代器上执行一个闭包函数,该闭包函数对每个元素进行检查,如果元素等于 k,就返回该元素在迭代器中的索引,否则返回 None。由于 position() 方法返回一个 Option<usize> 类型的值,因此还用了 unwrap() 方法来获取该值的实际值,如果获取失败则会触发 panic。最终返回的 k_index 就是元素 knums 数组中的位置。

|&x|这个是 Rust 闭包(closure)中的语法,用于表示闭包参数。|&x| 表示闭包接收一个参数,使用 x 来引用这个参数,而 & 表示参数是通过引用传递而不是值传递。| 符号用于表示闭包的开始和结束。在这个例子中,闭包用于在 nums 数组中查找值等于 k 的元素的下标位置。

image-20230316110236075