Rust每日一练(Leetday0026) 最小覆盖子串、组合、子集

news2024/11/26 9:50:51

 

目录

76. 最小覆盖子串 Minimum Window Substring  🌟🌟🌟

77. 组合 Combinations  🌟🌟

78. 子集 Subsets  🌟🌟

🌟 每日一练刷题专栏 🌟

Rust每日一练 专栏

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏


76. 最小覆盖子串 Minimum Window Substring

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"

示例 2:

输入:s = "a", t = "a"
输出:"a"

示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:

  • 1 <= s.length, t.length <= 10^5
  • s 和 t 由英文字母组成

进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?

 代码1: 滑动窗口

use std::collections::HashMap;

fn min_window(s: String, t: String) -> String {
    let s: Vec<u8> = s.into_bytes();
    let t: Vec<u8> = t.into_bytes();
    if s.len() < t.len() {
        return String::new();
    }
    let mut need: HashMap<u8, i32> = HashMap::new(); // 存储t中每个字符的出现次数
    for i in 0..t.len() {
        *need.entry(t[i]).or_insert(0) += 1;
    }
    let (mut left, mut right) = (0, 0); // 滑动窗口的左右指针
    let mut count = t.len(); // 记录滑动窗口中还需要的字符数
    let mut min_len = s.len() + 1; // 记录最小覆盖子串的长度
    let mut start = 0; // 记录最小覆盖子串的起始位置
    while right < s.len() {
        // 当右指针指向的字符是需要的字符,count减一
        if let Some(v) = need.get_mut(&s[right]) {
            if *v > 0 {
                count -= 1;
            }
            *v -= 1;
        }
        right += 1;
        // 当count为0时,说明滑动窗口中已经包含t中的所有字符
        while count == 0 {
            // 如果当前的覆盖子串更小,则更新最小覆盖子串的长度和起始位置
            if right - left < min_len {
                min_len = right - left;
                start = left;
            }
            // 当左指针指向的字符是需要的字符,count加一
            if let Some(v) = need.get_mut(&s[left]) {
                *v += 1;
                if *v > 0 {
                    count += 1;
                }
            }
            left += 1;
        }
    }
    if min_len == s.len() + 1 {
        "".to_string()
    } else {
        String::from_utf8_lossy(&s[start..start + min_len]).to_string()
    }
}

fn main() {
    println!("{}", min_window("ADOBECODEBANC".to_string(), "ABC".to_string()));
    println!("{}", min_window("a".to_string(), "a".to_string()));
    println!("{}", min_window("a".to_string(), "aa".to_string()));
}

代码2: 双指针

use std::collections::HashMap;

fn min_window(s: String, t: String) -> String {
    let mut need: HashMap<char, i32> = HashMap::new();
    let mut count = t.len() as i32;
    let (mut left, mut right, mut start, mut min_len) = (0, 0, 0, s.len() + 1);

    for c in t.chars() {
        *need.entry(c).or_insert(0) += 1;
    }

    let s = s.chars().collect::<Vec<_>>();

    while right < s.len() {
        if let Some(v) = need.get_mut(&s[right]) {
            if *v > 0 {
                count -= 1;
            }
            *v -= 1;
        }
        right += 1;

        while count == 0 {
            if right - left < min_len {
                min_len = right - left;
                start = left;
            }
            if let Some(v) = need.get_mut(&s[left]) {
                *v += 1;
                if *v > 0 {
                    count += 1;
                }
            }
            left += 1;
        }
    }

    if min_len == s.len() + 1 {
        "".to_owned() // 返回空字符串
    } else {
        s[start..start + min_len].iter().collect()
    }
}

fn main() {
    println!("{}", min_window("ADOBECODEBANC".to_string(), "ABC".to_string()));
    println!("{}", min_window("a".to_string(), "a".to_string()));
    println!("{}", min_window("a".to_string(), "aa".to_string()));
}

输出:

BANC
a
//空行


77. 组合 Combinations

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n

代码1: 回溯法

fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
    let mut res: Vec<Vec<i32>> = vec![]; // 存储所有组合
    let mut path: Vec<i32> = vec![]; // 存储当前组合

    fn backtrack(start: i32, n: i32, k: i32, path: &mut Vec<i32>, res: &mut Vec<Vec<i32>>) {
        if path.len() == k as usize { // 当前组合长度为k,加入结果中
            res.push(path.clone());
            return;
        }
        for i in start..=n { // 枚举可选数字
            path.push(i); // 加入当前数字
            backtrack(i + 1, n, k, path, res); // 从i+1开始枚举下一个数字
            path.pop(); // 撤销当前数字
        }
    }

    backtrack(1, n, k, &mut path, &mut res); // 从1开始枚举第一个数字
    res
}

fn main() {
    println!("{:?}", combine(4, 2));
    println!("{:?}", combine(1, 1));
}

输出:

[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
[[1]]

代码2: 枚举法

fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
    let mut res: Vec<Vec<i32>> = vec![]; // 存储所有组合
    for i in 0..1<<n { // 枚举所有二进制数
        let mut path: Vec<i32> = vec![]; // 存储当前组合
        for j in 1..=n { // 枚举n个数字
            if i & 1 << j-1 != 0 { // 当前数字被选中
                path.push(j);
            }
        }
        if path.len() == k as usize { // 当前组合长度为k,加入结果中
            res.push(path);
        }
    }
    res
}

fn main() {
    println!("{:?}", combine(4, 2));
    println!("{:?}", combine(1, 1));
}

78. 子集 Subsets

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10
  • nums 中的所有元素 互不相同

代码1:回溯法

fn subsets(nums: Vec<i32>) -> Vec<Vec<i32>> {
    let mut res: Vec<Vec<i32>> = vec![]; // 存储所有子集
    fn back_track (index: usize, path: &mut Vec<i32>, nums: &[i32], res: &mut Vec<Vec<i32>>) { // 递归枚举所有子集
        let tmp: Vec<i32> = path.to_vec(); // 将当前组合复制到临时数组中
        let n = nums.len();
        res.push(tmp); // 加入当前子集
        for i in index..n { // 枚举每个数字
            path.push(nums[i]); // 加入数字构成新的组合
            back_track (i+1, path, nums, res); // 递归枚举下一位数字
            path.pop(); // 移除数字
        }
    }
    back_track (0, &mut vec![], &nums, &mut res); // 从空集开始递归枚举所有子集
    res
}

fn main() {
    let nums: Vec<i32> = vec![1, 2, 3];
    println!("{:?}", subsets(nums));

    let nums: Vec<i32> = vec![0];
    println!("{:?}", subsets(nums));
}

输出:

[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
[[], [0]]

代码2: 循环枚举

fn subsets(nums: Vec<i32>) -> Vec<Vec<i32>> {
    let mut res: Vec<Vec<i32>> = vec![vec![]]; // 初始为空集
    for i in 0..nums.len() { // 枚举每个数字
        for sub in res.clone() { // 枚举已有的子集
            let mut temp = sub.clone();
            temp.push(nums[i]); // 加入当前数字
            res.push(temp); // 加入新的子集
        }
    }
    res
}

fn main() {
    let nums: Vec<i32> = vec![1, 2, 3];
    println!("{:?}", subsets(nums));

    let nums: Vec<i32> = vec![0];
    println!("{:?}", subsets(nums));
}

输出:

[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
[[], [0]]

代码3: 位运算

fn subsets(nums: Vec<i32>) -> Vec<Vec<i32>> {
    let mut res: Vec<Vec<i32>> = vec![]; // 存储所有子集
    let n = nums.len();
    for i in 0..(1 << n) { // 枚举所有二进制数
        let mut path: Vec<i32> = vec![]; // 存储当前子集
        for j in 0..n { // 枚举n个数字
            if i & (1 << j) != 0 { // 当前数字被选中
                path.push(nums[j]);
            }
        }
        res.push(path); // 加入当前子集
    }
    res
}

fn main() {
    let nums: Vec<i32> = vec![1, 2, 3];
    println!("{:?}", subsets(nums));

    let nums: Vec<i32> = vec![0];
    println!("{:?}", subsets(nums));
}

输出:

[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
[[], [0]]


🌟 每日一练刷题专栏 🌟

持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力! 

🌟 收藏,你的青睐是我努力的方向! 

评论,你的意见是我进步的财富!  

 主页:https://hannyang.blog.csdn.net/

Rust每日一练 专栏

(2023.5.16~)更新中...

Golang每日一练 专栏

(2023.3.11~)更新中...

Python每日一练 专栏

(2023.2.18~2023.5.18)暂停更

C/C++每日一练 专栏

(2023.2.18~2023.5.18)暂停更

Java每日一练 专栏

(2023.3.11~2023.5.18)暂停更

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/629727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML table表格详解

一、表格属性 表格属性 用法 border 代表表格边框厚度 width height 表格宽高 align table tr td 设置水平方向对齐方式 默认值left center right cellspacing 单元格到单元格距离 cellpadding 单元格文字到单元格边框距离 bgcolor 表格背景颜色 table tr td 都可以…

Win11 RTX 4090显卡深度学习环境配置(Nvidia显卡驱动、CUDA11.8.0)

Win11 RTX 4090显卡深度学习环境配置&#xff08;Nvidia显卡驱动、CUDA11.8.0&#xff09; 1. 简介2. 安装Anaconda3. 安装Pycharm4. 安装CUDA11.8.04.1 安装4.2 测试4.3 CUDA卸载 5. PyTorch安装5.1 PyTorch安装5.2 测试5.2.1 测试torch&#xff1a;5.2.2 测试CUDA&#xff1a…

chatgpt赋能python:切割字符串的Python技巧及实现方法

切割字符串的Python技巧及实现方法 在Python中操作字符串是比较常见的技巧&#xff0c;而对于需要将字符串切割成不同的元素&#xff0c;Python也提供了相应的方法。 split方法 split方法是Python字符串类中最常用的方法之一&#xff0c;它可以根据给定的分隔符对字符串进行…

学习HCIP的day.11

目录 十一、BGP的属性 1、权重属性 2、本地优先级 3、as-path 4、起源属性 5、MED --多出口的鉴别属性 十二、BGP选路规则 十三、BGP的社团属性 十四、BGP的在MA网络中的下一跳问题 五、BGP的认证 十一、BGP的属性 BGP协议在选路时&#xff0c;先对比属性&#xf…

在Spring Boot项目中连接SQL Server的几种方式

在Spring Boot项目中连接SQL Server 一. 使用Microsoft官方的SQL Server JDBC驱动连接&#xff1a;1. 依赖配置&#xff1a;2. YAML配置&#xff1a; 二. 使用第三方的jTDS驱动连接&#xff1a;1. 依赖配置&#xff1a;2. YAML配置&#xff1a; 三. 使用Microsoft提供的Spring …

动态网站Servelt基础

文章目录 一、Servlet基础&#xff08;一&#xff09;Servlet概述1、Servlet是什么2、Servlet容器3、Servlet应用程序的体系结构 &#xff08;二&#xff09;Servlet的特点1、功能强大2、可移植3、性能高效4、安全性高5、可扩展 &#xff08;三&#xff09;Servlet接口1、Servl…

chatgpt赋能python:Python中如何实现内循环到外循环

Python中如何实现内循环到外循环 Python是一种广泛使用的编程语言&#xff0c;其文本解析和数据结构操作灵活&#xff0c;让Python编程变得非常简单。在Python编程中&#xff0c;内循环到外循环是常见的问题&#xff0c;因此本文将着重介绍这个问题。 什么是内循环和外循环 …

「SQL面试题库」 No_93 广告效果

&#x1f345; 1、专栏介绍 「SQL面试题库」是由 不是西红柿 发起&#xff0c;全员免费参与的SQL学习活动。我每天发布1道SQL面试真题&#xff0c;从简单到困难&#xff0c;涵盖所有SQL知识点&#xff0c;我敢保证只要做完这100道题&#xff0c;不仅能轻松搞定面试&#xff0…

MyCat Docker 搭建与测试

mycat 是mysql分库分表的中间件&#xff0c;由java编写&#xff0c;本次进行mysql、mycat 的docker搭建&#xff0c;理解mycat的原理与特性。 一、mysql docker 搭建 这里启动两个实例&#xff1a; docker run -itd --name mysql1 -p 3307:3306 -e MYSQL_ROOT_PASSWORD123 m…

Golang每日一练(leetDay0092) 丑数 I\II Ugly Number i\ii

目录 263. 丑数 Ugly Number I &#x1f31f; 264. 丑数 Ugly Number II &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 263. 丑数 Ugl…

chatgpt赋能python:如何利用Python提高2022年的SEO效果

如何利用Python提高2022年的SEO效果 当谈到SEO时&#xff0c;Python已经成为了一种非常流行和有用的工具。在SEO的竞争激烈的时代&#xff0c;使用Python可帮助您找到各种创新方法来优化您的网站。在这篇文章中&#xff0c;我们将着重介绍Python的几种方法&#xff0c;来提高2…

高通开发系列 - 内核升级后音频驱动的开发和调试

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 背景概述msm8909平台codec框图msm8909内部控件的关系msm8909 数字codec内部处理流程驱动和dts的匹配问题msm8909 pm8909声卡部分的DTS…

chatgpt赋能python:Python怎么倒序输出列表

Python怎么倒序输出列表 介绍 Python是一种非常流行的编程语言&#xff0c;因为它具有简单易用和开放源代码的特点。使用Python可以进行许多操作&#xff0c;包括列表处理。列表是Python中常用的数据类型之一&#xff0c;它可以存储多个值并且可以通过下标访问。本文将介绍如…

chatgpt赋能python:Python内置函数:优化你的代码

Python内置函数&#xff1a;优化你的代码 在Python中&#xff0c;内置函数是非常重要的节省时间和简化代码的方法。Python内置了许多函数&#xff0c;可以在任何地方使用。无论从哪个角度看&#xff0c;这些函数都是编程中不可或缺的工具。在本篇文章中&#xff0c;我们将介绍…

chatgpt赋能python:Python如何切换中文

Python 如何切换中文 Python 是一种广泛使用的编程语言&#xff0c;被用于多种目的&#xff0c;包括数据分析、机器学习、Web 应用程序等。在使用 Python 进行开发时&#xff0c;需要处理不同的语言&#xff0c;其中中文也是包括在内的。对于需要切换中文的情况&#xff0c;本…

【考点】CKA 05_为 Kubernetes 运行 etcd 集群 etcd 备份与恢复

etcd 备份与恢复 1. 先决条件2. 内置快照2.1 安装 etcd2.2 获取 ENDPOINT 所提供的键空间的快照到文件 snapshotdb 注意&#xff01;&#xff01;&#xff01;在 harbor 仓库中准备好升级需要的镜像控制平面节点&#xff1a;升级 kubeadm控制平面节点&#xff1a;验证升级计划控…

《设计模式》之解释器模式

文章目录 1、定义2、动机3、类结构4、优缺点5、总结6、代码实现(C) 1、定义 给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一种解释器&#xff0c;这个解释器使用该表示来解释语言中的句子。 2、动机 在软件构建过程中&#xff0c;如果某一特定领域的问…

数据结构——栈,队列和数组

文章目录 **一 栈****1 基本概念****2 栈的顺序存储结构****2.1 顺序栈的实现****2.2 顺序栈的基本运算****2.3 共享栈** **3 栈的链式存储结构** **二 队列****1 基本概念****2 队列的顺序存储结构****2.1 队列的顺序存储****2.2 循环队列****2.3 循环队列的操作** **3 队列的…

JS 怎么理解ES6新增Set、Map两种数据结构?

目录 一、前言 二、Set 1.Set数据结构定义 2.Set数据结构的特性 3.Set数据结构的基本使用 4.Set遍历数据 5.Set 的使用场景 6.WeakSet的使用 7.垃圾回收机制 三、Map 1.Map数据结构定义 2.Map数据结构的特性 3.Map数据结构的基本使用 4.Map遍历数据 5.Map的使用场…

总结895

学习目标&#xff1a; 月目标&#xff1a;6月&#xff08;线性代数强化9讲&#xff0c;背诵15篇短文&#xff0c;考研核心词过三遍&#xff09; 周目标&#xff1a;线性代数强化3讲&#xff0c;英语背3篇文章并回诵&#xff0c;检测 每日必复习&#xff08;5分钟&#xff09;…