算法学习——LeetCode力扣回溯篇3

news2024/11/29 22:39:14

算法学习——LeetCode力扣回溯篇3

在这里插入图片描述

491. 非递减子序列

491. 非递减子序列 - 力扣(LeetCode)

描述

给你一个整数数组 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]]

提示

  • 1 <= nums.length <= 15
  • -100 <= nums[i] <= 100

代码解析

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    
    void backtracking(vector<int>& nums , int indnx )
    {
    	//小于2的不加入结果,至少两个
        if(path.size()>=2) result.push_back(path);
        if(indnx >= nums.size()) return;
		//用set统计每一层相同值元素的使用
        unordered_set<int> uset;
        for(int i =indnx ; i<nums.size(); i++)
        {
        	//如果当前值小于上一个,或者这个值在该层用过了,跳过
            if(path.empty() == 0 && nums[i] < path.back() 
                || uset.find(nums[i]) != uset.end()) 
            continue;
            //将该使用过的存入set,标记使用过
            uset.insert(nums[i]);
            path.push_back(nums[i]);
            backtracking(nums,i+1 );
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        backtracking(nums,0);
        return result;
    }
};

46. 全排列

46. 全排列 - 力扣(LeetCode)

描述

给定一个不含重复数字的数组 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]]

提示

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

代码解析

回溯法
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(vector<int> &nums)
    {
        if(path.size() == nums.size())
        {
            result.push_back(path);
            return;
        } 
        for(int i = 0 ; i<nums.size() ; i++)
        {
           auto it = find(path.begin(),path.end(),nums[i]);
           //如果这个元素在这个树枝之前用过,就跳出
           if(it == path.end()) 
           {
               path.push_back(nums[i]);
           }else
           {
               continue;
           }
            backtracking(nums);
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> permute(vector<int>& nums) {
        backtracking(nums);
        return result;
    }
};

回溯标记法

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    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; // path里已经收录的元素,直接跳过
            used[i] = true;
            path.push_back(nums[i]);
            backtracking(nums, used);
            path.pop_back();
            used[i] = false;
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        result.clear();
        path.clear();
        vector<bool> used(nums.size(), false);
        backtracking(nums, used);
        return result;
    }
};

47. 全排列 II

47. 全排列 II - 力扣(LeetCode)

描述

给定一个可包含重复数字的序列 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]]

提示

  • 1 <= nums.length <= 8
  • -10 <= nums[i] <= 10

代码解析

回溯标记法(不去重,时间复杂度高)

在插入之前做一个find查找,找不到相同的插入

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(vector<int>& nums , vector<bool>& used)
    {
        if(path.size() == nums.size())
        {
            if(find(result.begin() , result.end() , path) == result.end() ) result.push_back(path);
            return;
        }

        for(int i=0 ; i<nums.size() ;i++)
        {
            if(used[i] == 1) continue;

            used[i]=1;
            path.push_back(nums[i]);
            backtracking(nums,used);
            path.pop_back();
            used[i]=0;
        }
        return;
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<bool> used(nums.size(),false);
        backtracking(nums,used);
        return result;
    }
};

回溯去重
class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    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++) {
            // used[i - 1] == true,说明同一树枝nums[i - 1]使用过
            // used[i - 1] == false,说明同一树层nums[i - 1]使用过
            // 如果同一树层nums[i - 1]使用过则直接跳过
            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);
                path.pop_back();
                used[i] = false;
            }
        }
    }
public:
    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);
        return result;
    }
};

树层去重
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false)
{
    continue;
}

在这里插入图片描述

树枝去重
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true)
{
    continue;
}

在这里插入图片描述

332. 重新安排行程

332. 重新安排行程 - 力扣(LeetCode)

描述

给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。

所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。

例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前。
假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。

示例

示例 1:
在这里插入图片描述

输入:tickets = [[“MUC”,“LHR”],[“JFK”,“MUC”],[“SFO”,“SJC”],[“LHR”,“SFO”]]
输出:[“JFK”,“MUC”,“LHR”,“SFO”,“SJC”]

示例 2:

在这里插入图片描述

输入:tickets = [[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
输出:[“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解释:另一种有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”] ,但是它字典排序更大更靠后。

提示

  • 1 <= tickets.length <= 300
  • tickets[i].length == 2
  • fromi.length == 3
  • toi.length == 3
  • fromi 和 toi 由大写英文字母组成
  • fromi != toi

代码解析

回溯遍历(超时)

回溯遍历每一种可能
当出现第一种可能的路线,之间加入。
当出现新的可能路线,与老路线对比,如果字典排序小于,则替换老路线

class Solution {
public:
    vector<string> resul;
    vector<string> path;
    void backtraking(vector<vector<string>>& tickets , string Indnx ,  vector<bool> &used)
    {
    	//找到路线,看是否替换老的路径
    	//如果没有老路径直接加入,如果相同就返回,如果不同路径按照字典比较
        if(path.size()==tickets.size()+1)
        {
            if(resul.empty()==1) 
            {
                resul = path;
                return;
            }
            else if(resul == path) return;
            else 
            {
                for(int j=0 ;j<path.size();j++)
                {
                    for(int k=0 ;k<3;k++)
                    {
                        if(resul[j][k] == path[j][k]) continue;
                        else if(resul[j][k] < path[j][k])return;
                        else if(resul[j][k] > path[j][k]) 
                        {
                            resul.clear();
                            resul = path;
                            return;
                        }
                    }
                }
            }
            // cout<<"resu: ";
            // for(auto i:resul) cout<<i<<' ';
            // cout<<endl;
            return;
        }

        for(int i=0 ; i<tickets.size();i++)
        {
        	//如果当前机票使用过,或者当前机票目的地不对,跳过
            if(used[i]==true || tickets[i][0] != Indnx) continue;
            //如果当前机票可用,则加入路径
            if(used[i]== false && tickets[i][0] == Indnx)
            {
                used[i] = true;
                path.push_back(tickets[i][1]);
                //递归,确定递归找的新机票。下一站机票的开始机场,就是当前机票的目的地机场
                backtraking(tickets,tickets[i][1],used);
                used[i] = false;
                path.pop_back();
            }
        }
        return;
        
    }
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        vector<bool> used(tickets.size(),false);
        path.push_back("JFK");
        backtraking(tickets,"JFK",used);
        return resul;
    }
};

排序再回溯

先对输入票排序,其中排序按照票的目的地的字典减少排序(因为出发点是确定的,目的地多种找最优解)
之后回溯遍历找路线,发现的第一个路线即为最优路线

class Solution {
public:
	//按飞机票目的地(字符串vector第二个参数)字典减小排序
     class compare
    {
    public:
        bool operator()( const vector<string> tickets1 ,const  vector<string> tickets2 )
        {
           
            if((tickets1[1])[0]  < (tickets2[1])[0]) return 1;
            else if((tickets1[1])[0]  == (tickets2[1])[0])
            {
                if((tickets1[1])[1]  < (tickets2[1])[1]) return 1;
                else if((tickets1[1])[1]  == (tickets2[1])[1])
                {
                    if((tickets1[1])[2]  < (tickets2[1])[2]) return 1;
                    else return 0;
                }
                 return 0;
            }
            return 0;
           
        }
    };
    vector<string> resul;
    vector<string> path;
    bool find = false;
    void backtraking(vector<vector<string>>& tickets , string Indnx ,  vector<bool> &used)
    {
    	//找到一个路径就不找了,直接是最优路径
        if(find == true ) return;
        if(path.size()==tickets.size()+1)
        {
                resul = path;
                find =true;
                return;
        }

        for(int i=0 ; i<tickets.size();i++)
        {
            if(used[i]==true || tickets[i][0] != Indnx) continue;
            if(used[i]== false && tickets[i][0] == Indnx)
            {
                used[i] = true;
                path.push_back(tickets[i][1]);
                backtraking(tickets,tickets[i][1],used);
                used[i] = false;
                path.pop_back();
            }
        }
        return;
        
    }
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        vector<bool> used(tickets.size(),false);
        sort(tickets.begin(),tickets.end(),compare());
        // for(auto i:tickets) 
        // {
        //      cout<<'[';
        //     for(auto j:i)
        //     {
        //          cout<<j<<' ';
        //     }
        //      cout<<']';
        // }
           
        path.push_back("JFK");
        backtraking(tickets,"JFK",used);
        return resul;
    }
};

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

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

相关文章

第23讲 微信用户管理实现

package com.java1234.entity;import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data;import java.io.Serializable; import java.util.Date;/*** 微信用户信息实体* author java1234_小…

docker (三)-开箱即用常用命令

一 docker架构 拉取镜像仓库中的镜像到本地&#xff0c;镜像运行产生一个容器 registry 镜像仓库 registry可以理解为镜像仓库&#xff0c;用于保存docker image。 Docker Hub 是docker官方的镜像仓库&#xff0c;docker命令默认从docker hub中拉取镜像。我们也可以搭建自己…

【学网攻】 第(28)节 -- OSPF虚链路

系列文章目录 目录 系列文章目录 文章目录 前言 一、什么是OSPF虚链路&#xff1f; 二、实验 1.引入 实验目标 实验背景 技术原理 实验步骤 实验设备 实验拓扑图 实验配置 扩展 实验拓扑图 实验配置 实验验证 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻…

mac电脑上使用android studio创建flutter项目

mac电脑环境配置可以看这篇文章&#xff1a;https://xiaoshen.blog.csdn.net/article/details/136068650 配置玩环境之后&#xff0c;开始创建第一个flutter项目&#xff1a;点击new flutter project或者new project都可以 然后选择flutter&#xff1a; 并将sdk配置为解压后的…

Linux——网络通信TCP通信常用的接口和tco服务demo

文章目录 TCP通信所需要的套接字socket()bind()listen()acceptconnect() 封装TCP socket TCP通信所需要的套接字 socket() socket()函数主要作用是返回一个描述符&#xff0c;他的作用就是打开一个网络通讯端口&#xff0c;返回的这个描述符其实就可以理解为一个文件描述符&a…

【数位dp】【动态规划】【状态压缩】【推荐】1012. 至少有 1 位重复的数字

作者推荐 视频算法专题 本文涉及知识点 动态规划汇总 LeetCode:1012. 至少有 1 位重复的数字 给定正整数 n&#xff0c;返回在 [1, n] 范围内具有 至少 1 位 重复数字的正整数的个数。 示例 1&#xff1a; 输入&#xff1a;n 20 输出&#xff1a;1 解释&#xff1a;具有至…

Vue.js2+Cesium1.103.0 十五、计算方位角

Vue.js2Cesium1.103.0 十五、计算方位角 Demo <template><divid"cesium-container"style"width: 100%; height: 100%;"/> </template><script> /* eslint-disable no-undef */ /* eslint-disable new-cap */ /* eslint-disable n…

Java学习第十四节之冒泡排序

冒泡排序 package array;import java.util.Arrays;//冒泡排序 //1.比较数组中&#xff0c;两个相邻的元素&#xff0c;如果第一个数比第二个数大&#xff0c;我们就交换他们的位置 //2.每一次比较&#xff0c;都会产生出一个最大&#xff0c;或者最小的数字 //3.下一轮则可以少…

《Git 简易速速上手小册》第10章:未来趋势与扩展阅读(2024 最新版)

文章目录 10.1 Git 与开源社区10.1.1 基础知识讲解10.1.2 重点案例&#xff1a;Python 社区使用 Git10.1.3 拓展案例 1&#xff1a;Git 在大型开源项目中的角色10.1.4 拓展案例 2&#xff1a;支持开源项目的 Git 托管平台 10.2 新兴技术与 Git 的整合10.2.1 基础知识讲解10.2.2…

【机器学习笔记】5 机器学习实践

数据集划分 子集划分 训练集&#xff08;Training Set&#xff09;&#xff1a;帮助我们训练模型&#xff0c;简单的说就是通过训练集的数据让我们确定拟合曲线的参数。 验证集&#xff08;Validation Set&#xff09;&#xff1a;也叫做开发集&#xff08; Dev Set &#xf…

【蓝桥杯单片机入门记录】LED灯(附多个例程)

目录 一、LED灯概述 1.1 LED发光原理 1.2电路原理图 1.3电路实物图 1.4 开发板LED灯原理图 1.4.1共阳极LED灯操控原理&#xff08;本开发板&#xff09; &#xff08;非实际原理图&#xff0c;便于理解版本&#xff09;由图可以看出&#xff0c;每个LED灯的左边&#xf…

深度理解实分析:超越公式与算法的学习方法

在数学的学习旅程中&#xff0c;微积分和线性代数为许多学生提供了直观且具体的入门体验。它们通常依赖于明确的公式、算法以及解题步骤&#xff0c;而这些元素往往可以通过记忆和机械练习来掌握。然而&#xff0c;当我们迈入实分析的领域时&#xff0c;我们面临着一种全新的挑…

(06)Hive——正则表达式

Hive版本&#xff1a;hive-3.1.2 一、Hive的正则表达式概述 正则表达式是一种用于匹配和操作文本的强大工具&#xff0c;它是由一系列字符和特殊字符组成的模式&#xff0c;用于描述要匹配的文本模式。 Hive的正则表达式灵活使用解决HQL开发过程中的很多问题&#xff0c;本篇文…

vue3 之 倒计时函数封装

理解需求 编写一个函数useCountDown可以把秒数格式化为倒计时的显示xx分钟xx秒 1️⃣formatTime为显示的倒计时时间 2️⃣start是倒计时启动函数&#xff0c;调用时可以设置初始值并且开始倒计时 实现思路分析 安装插件 dayjs npm i dayjs倒计时逻辑函数封装 // 封装倒计时…

第24讲投票管理实现

投票管理实现 后端&#xff1a; package com.java1234.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.java1234.entity.*; import com.java1234.service.…

【PyQt】12-滑块、计数控件

文章目录 前言一、滑块控件 QSlider运行结果 二、计数器控件 QSpinBox运行结果 总结 前言 1、滑块控件 2、计数控件 一、滑块控件 QSlider #Author &#xff1a;susocool #Creattime:2024/2/15 #FileName:28-滑块控件 #Description: 通过滑块选择字体大小 import sys from PyQ…

DevOps落地笔记-21|业务价值:软件发布的最终目的

上一课时介绍如何度量软件的内部质量和外部质量。在外部质量中&#xff0c;我们提到用户满意度是衡量软件外部质量的关键因素。“敏捷宣言”的第一条原则规定&#xff1a;“我们最重要的目标&#xff0c;是通过持续不断的及早交付有价值的软件使用户满意”。从这一点也可以看出…

【C/C++内存管理详解】

C/C内存管理详解 1. C/C内存分布2. C语言中动态内存管理方式3. C中动态内存管理3.1 new/delete操作内置类型**3.2 new和delete操作自定义类型** 4. operator new与operator delete函数4.1 operator new与operator delete函数 5. new和delete的实现原理5.1 内置类型5.2 自定义类…

【开源】在线办公系统 JAVA+Vue.js+SpringBoot+MySQL

目录 1 功能模块1.1 员工管理模块1.2 邮件管理模块1.3 人事档案模块1.4 公告管理模块 2 系统展示3 核心代码3.1 查询用户3.2 导入用户3.3 新增公告 4 免责声明 本文项目编号&#xff1a; T 001 。 \color{red}{本文项目编号&#xff1a;T001。} 本文项目编号&#xff1a;T001。…

《合成孔径雷达成像算法与实现》Figure6.17

% rho_r = c/(2*Fr)而不是rho_r = c/(2*Bw) % Hsrcf exp函数里忘记乘pi了 clc clear close all参数设置 距离向参数设置 R_eta_c = 20e3; % 景中心斜距 Tr = 2.5e-6; % 发射脉冲时宽 Kr = 20e12; % 距离向调频率 alpha_os_r = 1.2;…