Leetcode算法训练日记 | day29

一、递增子序列

1.题目

Leetcode:第 491 题

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

示例 1:

输入:nums = [4,6,7,7]
输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]

示例 2:

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

2.解题思路

使用回溯算法来解决序列问题。findSubsequences 函数负责初始化并开始回溯过程。backtracking 函数是回溯算法的核心,它尝试在每个位置选择或不选择当前的元素,并递归地继续处理后续的元素。通过这种方式,backtracking 函数能够找到所有可能的子序列。使用一个大小为 201 的数组 used 来标记元素是否已经被使用过。这是因为数组 nums 中的元素值被假定为在 0 到 200 之间。如果 nums 中的元素值超出这个范围,需要相应地调整 used 数组的大小。此外,used 数组的索引是 nums[i] + 100,这是为了将 nums 中的元素值映射到 used 数组的索引范围内。

3.实现代码

#include <iostream>
#include <vector>
using namespace std;

class Solution {
public:
    vector<vector<int>> result;// 定义一个二维整数数组用于存储所有子序列的结果
    vector<int> path; // 定义一个一维整数数组用于存储当前子序列

    // 定义 backtracking 函数,用于实现回溯算法
    void backtracking(vector<int>& nums, int startIdex) {
        // 如果当前子序列的长度大于1,将其添加到结果集中
        if (path.size() > 1) {
            result.push_back(path);
        }

        // 定义一个数组用于标记数组中每个元素是否已经被使用过
        int used[201] = { 0 };
        // 遍历 nums 数组,从 startIdex 开始
        for (int i = startIdex; i < nums.size(); i++) {
            // 如果当前元素已经被添加到路径中,或者当前元素小于路径中最后一个元素,跳过
            if ((!path.empty() && nums[i] < path.back()) || used[nums[i] + 100] == 1) {
                continue;
            }
           
            used[nums[i] + 100] = 1; // 标记当前元素为已使用
            path.push_back(nums[i]);// 将当前元素添加到路径中 
            backtracking(nums, i + 1);// 递归调用 backtracking 函数,以当前元素的下一个元素作为新的起始索引
            path.pop_back();// 回溯:从路径中移除最后一个元素
        }
    }

    // 定义 findSubsequences 函数,用于生成所有子序列
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        // 清空结果集和路径,为生成新的子序列做准备
        result.clear();
        path.clear();
        backtracking(nums, 0); // 调用 backtracking 函数,开始回溯过程
        return result;// 返回结果集 result
    }
};



//测试
int main()
{
    Solution p;
    vector<vector<int>> result;
    vector<int>nums = { 4,6,7,7 };
    result = p.findSubsequences(nums);
    cout << "所有的组合有:" << endl;
    for (auto& ans : result) {
        cout << "[";
        for (auto& i : ans) {
            cout << i << " ";
        }
        cout << "]" << endl;
    }
    cout << endl;
    return 0;
}

 

二、全排列

1.题目

Leetcode:第 46 题

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

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

示例 2:

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

示例 3:

输入:nums = [1]
输出:[[1]]
2.解题思路

使用回溯算法来解决排列问题。permute 函数负责初始化并开始回溯过程。backtracking 函数是回溯算法的核心,它尝试在每个位置放置数组中的每个元素,并递归地继续处理后续的元素。通过这种方式,backtracking 函数能够找到所有可能的排列。used 向量是一个辅助工具,用于确保数组中的每个元素在当前排列中只出现一次,并允许回溯算法在必要时回退到之前的步骤,以探索其他可能的排列。这种方法可以生成包括重复元素在内的所有排列,如果数组中有重复元素,结果集中可能会出现重复的排列。如果需要排除重复的排列,可以增加额外的逻辑来检查新排列是否已经存在于结果集中。

3.实现代码
#include <iostream>
#include <vector>
using namespace std;

class Solution {
public:
    vector<vector<int>> result; // 定义一个二维整数数组用于存储所有排列的结果
    vector<int> path;// 定义一个一维整数数组用于存储当前排列

    // 定义 backtracking 函数,用于实现回溯算法
    void backtracking(vector<int>& nums, vector<bool>& used) {
        // 如果当前排列的长度等于原数组的长度,说明找到了一个完整的排列
        if (path.size() == nums.size()) {
            result.push_back(path);// 将当前排列添加到结果集中
            return; // 返回继续搜索其他排列
        }
        // 遍历数组中的每个元素
        for (int i = 0; i < nums.size(); i++) {
            // 如果该元素已经被使用过,则跳过
            if (used[i] == true) continue;
            used[i] = true;// 标记该元素为已使用
            path.push_back(nums[i]);// 将该元素添加到当前排列中
            backtracking(nums, used);// 递归调用 backtracking 函数,继续寻找下一个元素的排列
            path.pop_back();// 回溯:从当前排列中移除最后一个元素,尝试其他可能性
            used[i] = false;// 重置该元素为未使用状态,以便其他排列可以使用
        }
    }

    // 定义 permute 函数,用于生成所有排列
    vector<vector<int>> permute(vector<int>& nums) {
        // 清空结果集和当前排列,为生成新的排列做准备
        result.clear();
        path.clear();
        vector<bool> used(nums.size(), false);// 创建一个与 nums 数组大小相同的布尔向量,用于跟踪每个元素是否已使用
        backtracking(nums, used); // 调用 backtracking 函数,开始回溯过程
        return result;// 返回结果集 result,其中包含了所有可能的排列
    }
};

//测试
int main()
{
    Solution p;
    vector<vector<int>> result;
    vector<int>nums = { 1,2,3 };
    result = p.permute(nums);
    cout << "所有的组合有:" << endl;
    for (auto& ans : result) {
        cout << "[";
        for (auto& i : ans) {
            cout << i << " ";
        }
        cout << "]" << endl;
    }
    cout << endl;
    return 0;
}

 

三、全排列Ⅱ

1.题目

Leetcode:第 47 题

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:

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

示例 2:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
2.解题思路

使用回溯算法来解决排列问题。在这个类中,permuteUnique 函数首先清空结果集和当前路径,然后对输入数组 nums 进行排序。排序后,它创建一个布尔向量 used 来跟踪每个元素是否已被使用,并调用 backtracking 函数开始生成排列。backtracking 函数是回溯算法的核心,它尝试在每个位置放置数组中的每个元素,并递归地继续处理后续的元素。通过检查 i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false 来跳过与前一个未使用的元素相同的元素,从而避免生成重复的排列。这种方法可以生成数组的所有唯一排列,即使数组中有重复元素,结果集中也不会出现重复的排列。

3.实现代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Solution {
public: 
    vector<vector<int>> result;// 定义一个二维整数数组用于存储所有唯一排列的结果
    vector<int> path;// 定义一个一维整数数组用于存储当前正在构建的排列

    // 定义 backtracking 函数,用于实现回溯算法生成唯一排列
    void backtracking(vector<int>& nums, vector<bool>& used) {
        // 当前路径的长度等于原始数组的长度时,说明找到了一个完整的排列
        if (path.size() == nums.size()) {// 将当前路径添加到结果集中 
            result.push_back(path);    
            return;// 返回继续搜索其他排列
        }
        // 遍历数组中的每个元素
        for (int i = 0; i < nums.size(); i++) {
            // 如果当前元素与前一个元素相同,并且前一个元素未被使用过,则跳过当前元素以避免重复
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
                continue;
            }
            // 如果当前元素未被使用
            if (used[i] == false) {
                used[i] = true;// 标记当前元素为已使用
                path.push_back(nums[i]);// 将当前元素添加到路径中
                backtracking(nums, used);// 递归调用 backtracking 函数,继续寻找下一个元素的排列
                path.pop_back();// 回溯:从路径中移除最后一个元素,回退到上一步
                used[i] = false;// 重置当前元素为未使用状态,以便可以重新使用
            }
        }
    }

    // 定义 permuteUnique 函数,用于生成所有唯一排列
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        // 清空结果集和当前路径,为生成新的排列做准备
        result.clear();
        path.clear();
        sort(nums.begin(), nums.end());// 对输入数组进行排序,这样相同的元素会相邻,有助于避免重复排列
    
        vector<bool> used(nums.size(), false);// 创建一个布尔数组,用于跟踪数组中的每个元素是否已被使用 
        backtracking(nums, used);// 调用 backtracking 函数,开始回溯过程生成排列
        return result;// 返回包含所有唯一排列的结果集
    }
};



//测试
int main()
{
    Solution p;
    vector<vector<int>> result;
    vector<int>nums = { 1,2,2 };
    result = p.permuteUnique(nums);
    cout << "所有的组合有:" << endl;
    for (auto& ans : result) {
        cout << "[";
        for (auto& i : ans) {
            cout << i << " ";
        }
        cout << "]" << endl;
    }
    cout << endl;
    return 0;
}

 ps:以上皆是本人在探索算法旅途中的浅薄见解,诚挚地希望得到各位的宝贵意见与悉心指导,若有不足或谬误之处,还请多多指教。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

硬件?、嘉立创EDA画PCB规则设计

1、打开规则设计 设置单位为mil 点击全部 将安全距离设置为8mil&#xff0c;这个8mil是目前很多生产PCB的工厂可以做的&#xff0c;如果距离设置的更小也就是性能要求更高&#xff0c;相应的生产成本也高元件到元件的距离设置为20mil 2、设置导线的宽度规则&#xff0c;可以对v…

第G6周:CycleGAN实践

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、CycleGAN原理 &#xff08;一&#xff09;CycleGAN的原理结构&#xff1a; CycleGAN&#xff08;循环生成对抗网络&#xff09;是一种生成对抗网络&…

思维导图软件Xmind for Mac 中文激活版 支持M

XMind是一款非常受欢迎的思维导图软件&#xff0c;它应用了Eclipse RCP软件架构&#xff0c;注重易用性、高效性和稳定性&#xff0c;致力于帮助用户提高生产率。 Xmind for Mac 中文激活版下载 XMind的程序主体由一组插件构成&#xff0c;包括一个核心主程序插件、一组Eclipse…

文件后缀变成.halo? 如何恢复重要数据

.halo 勒索病毒是什么&#xff1f; .halo勒索病毒是一种恶意软件&#xff0c;属于勒索软件&#xff08;Ransomware&#xff09;的一种。这种病毒会加密用户计算机上的文件&#xff0c;并要求受害者支付赎金才能获取解密密钥&#xff0c;从而恢复被加密的文件。勒索软件通常会通…

力扣(leetcode) 42. 接雨水 (带你逐步思考)

力扣(leetcode) 42. 接雨水 &#xff08;带你逐步思考&#xff09; 链接&#xff1a;https://leetcode.cn/problems/trapping-rain-water/ 难度&#xff1a;hard 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多…

【方便 | 重要】#LLM入门 | Agent | langchain | RAG # 3.7_代理Agent,使用langchain自带agent完成任务

大型语言模型&#xff08;LLMs&#xff09;虽强大&#xff0c;但在逻辑推理、计算和外部信息检索方面能力有限&#xff0c;不如基础计算机程序。例如&#xff0c;LLMs处理简单计算或最新事件查询时可能不准确&#xff0c;因为它们仅基于预训练数据。LangChain框架通过“代理”(…

机器学习在安全领域的应用:从大数据中识别潜在安全威胁

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

Ubuntu20.04 ISAAC SIM仿真下载使用流程(4.16笔记补充)

机器&#xff1a;华硕天选X2024 显卡&#xff1a;4060Ti ubuntu20.04 安装显卡驱动版本&#xff1a;525.85.05 参考&#xff1a; What Is Isaac Sim? — Omniverse IsaacSim latest documentationIsaac sim Cache 2023.2.3 did not work_isaac cache stopped-CSDN博客 Is…

LeetCode in Python 704. Binary Search (二分查找)

二分查找是一种高效的查询方法&#xff0c;时间复杂度为O(nlogn)&#xff0c;本文给出二分查找的代码实现。 示例&#xff1a; 代码&#xff1a; class Solution:def search(self, nums, target):l, r 0, len(nums) - 1while l < r:mid (l r) // 2if nums[mid] > ta…

C++11 数据结构1 线性表的概念,线性表的顺序存储,实现,测试

一 线性表的概念 线性结构是一种最简单且常用的数据结构。 线性结构的基本特点是节点之间满足线性关系。 本章讨论的动态数组、链表、栈、队列都属于线性结构。 他们的共同之处&#xff0c;是节点中有且只有一个开始节点和终端节点。按这种关系&#xff0c;可以把它们的所有…

MC9S12A64 程序烧写方法

前言 工作需要对MC9S12A64 单片机进行程序烧写。 资料 MC9S12A64 单片机前身属于 飞思卡尔半导体&#xff0c;后来被恩智浦收购&#xff0c;现在属于NXP&#xff1b; MC9S12A64 属于16位S12系列&#xff1b;MC9S12 又叫 HCS12。 数据手册下载连接 S12D_16位微控制器 | N…

[大模型]TransNormerLLM-7B 接入 LangChain 搭建知识库助手

TransNormerLLM-7B 接入 LangChain 搭建知识库助手 环境准备 在 autodl 平台中租赁一个 3090/4090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8 接下来打开刚刚租用服务器的 JupyterLab&#xff0c;并且打开其…

简单实用的备忘录小工具 记事提醒备忘效果超好

在这个信息爆炸的时代&#xff0c;我们每个人都需要处理大量的信息和任务。有时候&#xff0c;繁忙的生活和工作会让我们感到压力山大。幸运的是&#xff0c;现在有很多简单实用的软件工具&#xff0c;像得力的小助手一样&#xff0c;帮助我们整理思绪&#xff0c;提高效率&…

Redis系列1:深刻理解高性能Redis的本质

1 背景 分布式系统绕不开的核心之一的就是数据缓存&#xff0c;有了缓存的支撑&#xff0c;系统的整体吞吐量会有很大的提升。通过使用缓存&#xff0c;我们把频繁查询的数据由磁盘调度到缓存中&#xff0c;保证数据的高效率读写。 当然&#xff0c;除了在内存内运行还远远不够…

Docker 和 Podman的区别

文章目录 Docker 和 Podman的区别安装架构和特权要求运行容器方面安全性(root的权限)镜像管理方面命令方面Docker常用命令Podman常用命令 Docker 和 Podman的区别 安装 Docker安装&#xff1a;官方文档 Podman安装&#xff1a;官方文档 架构和特权要求 Docker使用client-se…

11、电科院FTU检测标准学习笔记-越限及告警上送功能

作者简介&#xff1a; 本人从事电力系统多年&#xff0c;岗位包含研发&#xff0c;测试&#xff0c;工程等&#xff0c;具有丰富的经验 在配电自动化验收测试以及电科院测试中&#xff0c;本人全程参与&#xff0c;积累了不少现场的经验 ———————————————————…

git 快问快答

我在实习的时候&#xff0c;是用本地开发&#xff0c;然后 push 到 GitHub 上&#xff0c;之后再从 Linux 服务器上拉 GitHub 代码&#xff0c;然后就可以了。一般程序是在 Linux 服务器上执行的&#xff0c;我当时使用过用 Linux 提供的命令来进行简单的性能排查。 在面试的时…

详解爬虫基本知识及入门案列(爬取豆瓣电影《热辣滚烫》的短评 详细讲解代码实现)

目录 前言什么是爬虫&#xff1f; 爬虫与反爬虫基础知识 一、网页基础知识 二、网络传输协议 HTTP&#xff08;HyperText Transfer Protocol&#xff09;和HTTPS&#xff08;HTTP Secure&#xff09;请求过程的原理&#xff1f; 三、Session和Cookies Session Cookies Session与…

抖音小店流量差怎么办?做好这三大细节,就可以完美解决!

大家好&#xff0c;我是电商糖果 很多刚开店的朋友&#xff0c;遇到的第一个难题就是店铺流量差。 没有流量&#xff0c;也就不会出单&#xff0c;更别提起店了。 糖果做抖音小店四年多了&#xff0c;也开了很多家小店。 很多新店没有流量&#xff0c;其实主要原因是这三个…

在mysql函数中启动事物和行锁/悲观锁实现并发条件下获得唯一流水号

业务场景 我有一个业务需求&#xff1a;我有一个报卡表 report里面有一个登记号字段 fcardno、地区代码 faddrno和发病年份 fyear&#xff0c;登记号由**“4位地区代码”“00”“发病年份”“5位流水号”**组成&#xff0c;我要在每次插入一张报卡&#xff08;每一行数据&#…