Leetcode算法训练日记 | day29

news2024/11/16 16:34:31

一、递增子序列

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

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

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

相关文章

【配电网故障定位】基于二进制蝙蝠算法的配电网故障定位 33节点配电系统故障定位【Matlab代码#80】

文章目录 【获取资源请见文章第6节&#xff1a;资源获取】1. 配电网故障定位2. 二进制蝙蝠算法3. 算例展示4. 部分代码展示5. 仿真结果展示6. 资源获取 【获取资源请见文章第6节&#xff1a;资源获取】 1. 配电网故障定位 配电系统故障定位&#xff0c;即在配电网络发生故障的…

基于SpringBoot的在线五子连珠的设计与实现,前端采用vue框架;后端采用SpringBoot,mybatis

介绍 基于SpringBoot的在线五子连珠的设计与实现&#xff0c;主要是设计一款五子棋游戏&#xff0c;涉及登录注册的功能&#xff0c;人机对战、联机对战和积分排行榜的功能。其中人机对战中&#xff0c;电脑采用的是采用了一种基于局面分析的评分算法来确定机器人的下一步落子…

基于Python dlib的实时人脸识别,附源码

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

CSS背景设置

目录 背景颜色 背景图片 背景平铺 背景图片位置 背景图片固定 背景样式综合书写 背景色半透明 通过 CSS 背景属性&#xff0c;可以给页面元素添加背景样式。背景属性可以设置背景颜色、背景图片、背景平铺、背景图片位置、背景图像固定等 背景颜色 在CSS中可以使用bac…

Count the Values of k

目录 题目总览 思路 参考代码 原题链接&#xff1a; CF1933C Turtle Fingers: Count the Values of k 题目总览 # Turtle Fingers: Count the Values of k ## 题面翻译 给你三个**正**整数 $a$ 、 $b$ 和 $l$ ( $a,b,l>0$ )。 可以证明&#xff0c;总有一种方法可以选择*…

机器学习——模型融合:Stacking算法

机器学习——模型融合&#xff1a;Stacking算法 在机器学习中&#xff0c;模型融合是一种常用的方法&#xff0c;它可以提高模型的泛化能力和预测性能。Stacking算法&#xff08;又称为堆叠泛化&#xff09;是一种强大的模型融合技术&#xff0c;它通过组合多个基本分类器的预…

hive了解系列一

“ 随着智能手机的普及&#xff0c;互联网时代红利的爆发&#xff0c;用户数量和产生的数据也越发庞大。为了解决这个问题&#xff0c;提高数据的使用价值。 Hadoop生态系统就被广泛得到应用。 在早期&#xff0c;Hadoop生态系统就是为处理如此大数据集而产生的一个合乎成本效益…

C# 整数转罗马数字

罗马数字包含以下七种字符:I&#xff0c;V&#xff0c;X&#xff0c;L&#xff0c;C,D和M。 例如&#xff0c;罗马数字2写做 II &#xff0c;即为两个并列的 1。12 写做XII&#xff0c;即为XII。27写做 XXVII,即为XXV II 。 通常情况下&#xff0c;罗马数字中小的数字在大的数字…

MoJoCo 入门教程(七)XML 参考

系列文章目录 前言 表格第二列中的符号含义如下&#xff1a; ! 必填元素&#xff0c;只能出现一次 ? 可选元素&#xff0c;只能出现一次 * 可选元素&#xff0c;可多次出现 R 可选元素&#xff0c;可递归出现多次 一、简介 本章是 MuJoCo 中使用的 MJCF 建模语言的参考手册。…

03-JAVA设计模式-享元模式

享元模式 什么是享元模式 享元模式&#xff08;Flyweight Pattern&#xff09;是一种对象结构型设计模式&#xff0c;用于减少创建对象的数量&#xff0c;以减少内存占用和提高系统性能。它通过共享已经存在的对象来避免创建大量相似的对象&#xff0c;从而降低内存消耗。 在…

vue3.0项目生成标签条形码(插件:jsbarcode)并打印(插件:Print.js)支持pda扫码枪扫描

文章目录 功能场景生成条形码设置打印功能踩坑 功能场景 功能场景&#xff1a;供应链中对一些货品根据赋码规则进行赋码&#xff0c;赋码之后生成根据赋码结果生成条形码&#xff0c;执行打印功能&#xff0c;贴在货品之上&#xff0c;打印之后可以用pda的手枪进行扫描&#x…

蓝桥杯2024年第十五届省赛真题-数字接龙

思路&#xff1a;DFS&#xff0c;因为输入的i&#xff0c;j的顺序导致&#xff0c;方向向量中x是行编号&#xff0c;y是列编号。方向向量可能和直觉上不同。 错的 //int dx[8]{0,1,1,1,0,-1,-1,-1}; //int dy[8]{1,1,0,-1,-1,-1,0,1}; 对的 int dx[]{-1,-1,0,1,1,1,0,-1}; int…

Hotcoin4月16日上新热门资产:头部RWA技术提供方Centrifuge(CFG)

Hotcoin持续为全球600万用户发掘优质潜力资产&#xff0c;热门币种交易上热币。一文快速了解今日上新资产:Centrifuge(CFG) 推荐指数 8.2 交易对 CFG/USDT 交易时间 4月16日 19:00 资产赛道 RWA 项目简介 Centrifuge是一个去中心化资产融资协议&#xff0c;专注于释放现实世界资…

计算机视觉——基于OpenCV和Python进行模板匹配

模板匹配&#xff1f; 模板匹配是它允许在一幅较大的图像中寻找是否存在一个较小的、预定义的模板图像。这项技术的应用非常广泛&#xff0c;包括但不限于图像识别、目标跟踪和场景理解等。 目标和原理 模板匹配的主要目标是在一幅大图像中定位一个或多个与模板图像相匹配的…

05.MySQL索引事务

1. 索引 1.1 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。 可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#xff0c;各类索引有各自的数据结构实现 1.2 作用 数据库中的表、数据、索引之间的关系&#xff0c;类似于书架上的…

链表创建的陷阱与细节

链表是线性表的一种&#xff0c;它在逻辑结构上是连续的&#xff0c;在物理结构上是非连续的。 也就是说链表在物理空间上是独立的&#xff0c;可能是东一块西一块的。如下顺序表和链表在内存空间上的对比&#xff1a; 而链表的每一块空间是如何产生联系实现在逻辑结构上是连续…

pycharm永久改变sys.path

进入pycharm&#xff0c;选择file->settings->interpreter 在这里选择图中所示show all 再单击左上角减号右侧第三个&#xff0c;长得像思维导图的图标 之后添加你的路径&#xff0c;确认即可

vim使用指南:指令、配置、插件、异常

文章目录 vi / vim命令模式插入模式光标定位复制粘贴删除撤销替换删除查找 底行模式保存退出行号查找多开其他 视图模式注释 异常vim配置vim插件 vi / vim vim的本质是一个编辑器&#xff0c;是一种多模式的编辑器&#xff0c;只能进行读写操作&#xff0c;不能进行编译编辑器…

jmeter-while控制器用法

condition中添加while结束循环的条件&#xff0c;以下语句的意思是&#xff0c;当percent等于100时&#xff0c;就跳出while循环继续执行 ${__javaScript("${percent}" ! 100)} 举例&#xff0c;以下方法是getPercent为一个引出的异步接口&#xff0c;该接口的返回包…

uni-admin中引入uni-cms的缺少schema及uni-media-library缺少云函数的问题

1. 在管理端运行提示一些表找不到&#xff0c;因为是uni-admin关联的uni-starter的服务空间&#xff0c;在uni-admin的uniCloud中没有内容&#xff0c;在uni-starter的uniCloud中也没有发现对应的表&#xff0c;后面干脆在云端找到对应的表之后新建了&#xff0c;然后再下载到本…