算法训练营day29

一、组合

参考链接77. 组合 - 力扣(LeetCode)

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;public class Solution {public List<List<Integer>> combine  (int n, int k) {List<List<Integer>> res = new ArrayList<>();if (k <= 0 || n < k) {return res;}Deque<Integer> path = new ArrayDeque<>();dfs(n, k, 1, path, res);return res;}private void dfs(int n, int k, int index, Deque<Integer> path, List<List<Integer>> res) {//如果当前path的大小和 k相等,则将结果保存到ArrayList当中if (path.size() == k) {res.add(new ArrayList<>(path));return;}// 剪枝优化 i <= n - (k - path.size()) + 1 背吧,归纳法for (int i = index; i <= n - (k - path.size()) + 1; i++) {path.addLast(i);dfs(n, k, i + 1, path, res);path.removeLast();}}
}
二、递增子序列

核心理解:set去重

set在dfs的实现的方式是 new HashSet<>(),而不是在函数外定义的set,每一次递归都会生成新的Set,

class Solution {// 定义全局变量保存结果List<List<Integer>> res = new ArrayList<>();public List<List<Integer>> findSubsequences(int[] nums) {// idx 初始化为 -1,开始 dfs 搜索。dfs(nums, -1, new ArrayList<>());return res;}private void dfs(int[] nums, int idx, List<Integer> curList) {// 只要当前的递增序列长度大于 1,就加入到结果 res 中,然后继续搜索递增序列的下一个值。if (curList.size() > 1) {res.add(new ArrayList<>(curList));}// 在 [idx + 1, nums.length - 1] 范围内遍历搜索递增序列的下一个值。// 借助 set 对 [idx + 1, nums.length - 1] 范围内的数去重。
//注意 set是 数中每一层的 变量,到达下一层时又new了HashSetSet<Integer> set = new HashSet<>();for (int i = idx + 1; i < nums.length; i++) {// 1. 如果 set 中已经有与 nums[i] 相同的值了,说明加上 nums[i] 后的所有可能的递增序列之前已经被搜过一遍了,因此停止继续搜索。if (set.contains(nums[i])) { continue;}set.add(nums[i]);// 2. 如果 nums[i] >= nums[idx] 的话,说明出现了新的递增序列,因此继续 dfs 搜索(因为 curList 在这里是复用的,因此别忘了 remove 哦)if (idx == -1 || nums[i] >= nums[idx]) {curList.add(nums[i]);dfs(nums, i, curList);curList.remove(curList.size() - 1);}}}
}
  1. 比如 4 7 3 2 1 7 … 这个数组,当curList遍历到 4 7 的时候,进入递归,一直遍历直到 出现 第二个7,这时候出现了 4 7 7 序列添加到结果中
  2. 回溯到 4 7 ,在当前层的for循环进行遍历,再次遍历到 第二个 7,判断set中有7,通过1我们知道 4 7 7 开头的数组组合我们在递归中已经将其实现,所以这一枝我们进行剪枝
  3. 回归set的作用,处理数组中出现相同值时 出现重复结果(也就是去重)

参考链接46. 全排列 - 力扣(LeetCode)

三、全排列
import java.util.ArrayList;
import java.util.List;public class Solution {public List<List<Integer>> permute(int[] nums) {int len = nums.length;// 使用一个动态数组保存所有可能的全排列List<List<Integer>> res = new ArrayList<>();if (len == 0) {return res;}//使用一个数组表示某个数是否已经被选过,选过为true,否则为falseboolean[] used = new boolean[len];List<Integer> path = new ArrayList<>();dfs(nums, len, 0, path, used, res);return res;}
//nums 当前数组,len 数组长度,depth表示深度,path 当前走过的路径,used 某个数字是否被选中, res 结果数组private void dfs(int[] nums, int len, int depth,List<Integer> path, boolean[] used,List<List<Integer>> res) {
// 如果遍历到 深度 和 长度 相等表示所有数字都已经被选择过了if (depth == len) {res.add(path);return;}// 在非叶子结点处,产生不同的分支,这一操作的语义是:在还未选择的数中依次选择一个元素作为下一个位置的元素,这显然得通过一个循环实现。 ****这段是重点核心代码,需要背for (int i = 0; i < len; i++) {if (!used[i]) {path.add(nums[i]);used[i] = true;dfs(nums, len, depth + 1, path, used, res);// 注意:下面这两行代码发生 「回溯」,回溯发生在从 深层结点 回到 浅层结点 的过程,代码在形式上和递归之前是对称的used[i] = false;path.remove(path.size() - 1);}}}public static void main(String[] args) {int[] nums = {1, 2, 3};Solution solution = new Solution();List<List<Integer>> lists = solution.permute(nums);System.out.println(lists);}
}
四、全排列2

使用存在重复数字的数组来生成新的全排列数组,要求去重

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;public class Solution {public List<List<Integer>> permuteUnique(int[] nums) {int len = nums.length;List<List<Integer>> res = new ArrayList<>();if (len == 0) {return res;}// 排序(升序或者降序都可以),排序是剪枝的前提Arrays.sort(nums);boolean[] used = new boolean[len];// 使用 Deque 是 Java 官方 Stack 类的建议Deque<Integer> path = new ArrayDeque<>(len);dfs(nums, len, 0, used, path, res);return res;}private void dfs(int[] nums, int len, int depth, boolean[] used, Deque<Integer> path, List<List<Integer>> res) {if (depth == len) {res.add(new ArrayList<>(path));return;}for (int i = 0; i < len; ++i) {if (used[i]) {continue;}// 剪枝条件:i > 0 是为了保证 nums[i - 1] 有意义// 写 !used[i - 1] 是因为 nums[i - 1] 在深度优先遍历的过程中刚刚被撤销选择,被撤销选择为falseif (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue;}path.addLast(nums[i]);used[i] = true;dfs(nums, len, depth + 1, used, path, res);// 回溯部分的代码,和 dfs 之前的代码是对称的used[i] = false;path.removeLast();}}
}

A 1分24秒到2分00秒:讲了为什么要先排序 因为结果是要去重的,而结果都是列表形式的,那列表怎么判重呢?就是排序之后一个一个的比较,所以那还不如先排序之后再计算,在计算的过程中判断是否有重复,免得对每个结果再做一次排序去重操作。再一个,排序之后相同的元素一定重复吗?不一定,不同结果经过排序之后也可能相同

B 为什么" nums[i-1] 的used状态是被选择的,那么说明当前的nums[i] 是 nums[i-1]的下一层路径。"

原因:因为往下层递归的话,一直再往下层走,dfs还未return,也就是说used还没有被回溯为未选择状态,所以同一条分支上,nums[i-1] 的used状态一定是被选择的。

为什么“ 如果 nums[i-1] 的状态是没被选择的,那么说明当前 的nums[i] 是nums[i-1] 同层路径。”

原因:递归到叶节点,开始往上回溯了,回溯到某一层时把used[i-1]回溯为未选择状态,然后for循环i++横向移动,自然这时再判断used[i-1]就一定是未选择状态。

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

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

相关文章

C语言----斐波那契数列

各位看官们好&#xff0c;当我写了上一篇博客杨辉三角后&#xff0c;有一些看官叫我讲一下斐波那契数列。对于这个大家应该是有了解的。最简单的规律就是f(n)f(n-2)f(n-1)。就是当前是前两项之和&#xff0c;然后下标1和0都是1.从第三项开始计算的。那么我们知道规律&#xff0…

选购洗地机有哪些技巧?2024洗地机全面解析,618洗地机综合对比

洗地机作为人们生活中智能清洁工具的代表&#xff0c;它自带清/污水箱&#xff0c;不用手洗滚刷&#xff0c;既可以吸尘也可以自动识别并清洗地板上的干湿垃圾和顽固污渍&#xff0c;它以多功能一体化的设计改善了家务清洁的效率和体验。那么如何在众多洗地机品牌中&#xff0c…

C#实现简单音乐文件解析播放——Windows程序设计作业2

1. 作业内容 编写一个C#程序&#xff0c;要求实现常见音乐文件的播放功能&#xff0c;具体要求如下&#xff1a;     1). 播放MP3文件&#xff1a; 程序应能够读取MP3文件&#xff0c;并播放其中的音频。     2). 播放OGG文件&#xff1a; 应能够播放ogg文件。     …

阿里云Redis创建使用

说明&#xff1a;本文介绍如何使用阿里云Redis&#xff0c;包括开通、连接、使用&#xff1b; 开通 进入官网Redis产品页&#xff0c;点击免费试用&#xff08;白嫖&#xff09;&#xff1b; 选择中间这个&#xff0c;云数据库Redis版&#xff1b; 开通完成后&#xff0c;可在…

如何在Java项目中使用Spring Boot快速连接达梦数据库(DM)

前言 在Java开发领域&#xff0c;Spring Boot凭借其简洁快速的特性成为现代应用开发的首选框架。本文将详细介绍如何在Spring Boot项目中整合JDBC以快速连接达梦数据库(DM)&#xff0c;并提供一个简单的示例来验证连接是否成功。 一、环境准备与依赖配置 在开始之前&#xf…

零代码平台助力中国石化江苏油田实现高效评价体系

概述&#xff1a; 中国石化集团江苏石油勘探局有限公司面临着评价体系依赖人工处理数据、计算繁琐且容易出错的挑战。为解决这一问题&#xff0c;他们决定借助零代码平台明道云开发江苏油田高质量发展经济指标评价系统。该系统旨在实现原始数据批量导入与在线管理、权重及评分…

QT设计模式:建造者模式

基本概念 建造者模式是一种创建型设计模式&#xff0c;它允许你创建复杂对象的过程独立于该对象的组成部分以及它们的组装方式。这样可以构造出不同的对象表示。 在建造者模式中&#xff0c;将创建对象的过程和对象的表示分离&#xff0c;通过一步步的构建&#xff0c;可以得…

FFmpeg常用API与示例(四)——过滤器实战

1.filter 在多媒体处理中&#xff0c;filter 的意思是被编码到输出文件之前用来修改输入文件内容的一个软件工具。如&#xff1a;视频翻转&#xff0c;旋转&#xff0c;缩放等。 语法&#xff1a;[input_link_label1]… filter_nameparameters [output_link_label1]… 1、视…

C++中调用python函数(VS2017+WIN10+Anaconda虚拟环境)

1.利用VS创建C空项目 step1 文件——新建——项目 step2 Visual C—— Windows桌面——Windows桌面向导 step3 选择空项目 step4 源文件——新建项——添加 step5 Visual C——C文件&#xff08;.cpp&#xff09; 2.配置环境 Step1. 更换成Release与X64 Step2. 打开项目属性&…

文本提取新技能:学会按行数批量提取,轻松应对各种需求

在数字化时代&#xff0c;文本处理成为我们日常生活和工作中不可或缺的一部分。无论是从网页、文档还是数据库中提取信息&#xff0c;文本提取技能都显得尤为重要。而按行数批量提取文本内容&#xff0c;更是文本处理中的一项高效且实用的技能。本文将介绍办公提效工具如何按行…

在Spring Boot应用安装SSL证书

目录 前提条件 步骤一&#xff1a;下载SSL证书 步骤二&#xff1a;在Spring Boot安装SSL证书 步骤三&#xff1a;验证SSL证书是否安装成功 前提条件 已通过数字证书管理服务控制台签发证书SSL证书绑定的域名已完成DNS解析&#xff0c;即您的域名与主机IP地址相互映射已在W…

ASP.NET学生信息管理系统

摘 要 本文介绍了在ASP.net环境下采用“自上而下地总体规划&#xff0c;自下而上地应用开发”的策略开发一个管理信息系统的过程。通过分析某一学校学生管理的不足&#xff0c;创建了一套行之有效的计算机管理学生的方案。文章介绍了学生管理信息系统的系统分析部分&#xff0c…

微信投票源码系统至尊版 吸粉变现功能二合一

源码简介 微信投票系统在营销和社交互动中发挥着多方面的作用&#xff0c;它能够提升用户的参与度和品牌曝光度&#xff0c;还是一种有效的数据收集、营销推广和民主决策工具。 分享一款微信投票源码系统至尊版&#xff0c;集吸粉变现功能二合一&#xff0c;全网独家支持礼物…

已经安装tensorflow,仍报错No module named ‘tensorflow‘

在安装某些python虚拟环境的教程文章中&#xff0c;经常看到有评论区说安装了但是调用显示无模块&#xff0c;例如pytorch和tensorflow等等。 其实跟之前我写过的一篇文章解决方法类似&#xff0c;就是python项目中需要应用哪个虚拟环境&#xff0c;这个项目的python解释器就选…

企业网络需求及适合的解决方案

近年来&#xff0c;企业网络通信需求可谓五花八门&#xff0c;变幻莫测。它不仅为企业的生产、办公、研发、销售提供全面赋能&#xff0c;同时也让企业业务规模变大成为了可能。 在当前的技术格局下&#xff0c;中大型企业常见的技术方案有很多&#xff0c;而同时也有各自不可替…

商务英语口语成人考级外语培训之BECkao考级口语篇

在口语考试中&#xff0c;不管实际内容你能说出多少&#xff0c;但准备一些套话&#xff0c;至少还能撑撑场子你们说是不是&#xff1f; 内容阐述 描述事实 1.Im going to describe/present/explain/give you some information about... 2.Id like to say a few words about...…

德国储能项目锂电池储能集装箱突发火灾:安全挑战再引关注

2024年4月27日&#xff0c;德国尼尔莫尔商业区的一起锂电池储能集装箱火灾事件引起了全球关注。这起事故不仅导致两名消防员在救援过程中受伤&#xff0c;更暴露了储能系统在安全领域亟待解决的重要问题。 根据德国消防队的出警记录&#xff0c;火灾发生在晚上9点前不久。消防人…

机器学习算法应用——神经网络回归任务、神经网络分类任务

神经网络回归任务&#xff08;4-3&#xff09; 神经网络回归任务&#xff0c;通常指的是使用神经网络模型进行回归分析。回归分析是一种统计学方法&#xff0c;用于研究一个或多个自变量&#xff08;预测变量&#xff09;与一个因变量&#xff08;响应变量&#xff09;之间的关…

涨薪技术 —— 搞定Appium工作中常见应用操作!

前言 Appium 是一个开源、跨平台的自动化测试工具&#xff0c;用于测试原生和轻量移动应用&#xff0c;支持 iOS, Android 和 FirefoxOS 平台。此工具在测试工作中也较长用到&#xff0c;接下来给大家介绍日常中的操作。 1、应用操作 1.1获取应用的包名和界面名 当我们从一…

日报表定时任务优化历程

报表需求背景 报表是一个很常见的需求&#xff0c;在项目中后期往往会需要加多种维度的一些统计信息&#xff0c;今天就来谈谈上线近10个月后的一次报表优化优化之路&#xff08;从一天报表跑需要五分钟&#xff0c;优化至秒级&#xff09; 需求&#xff1a;对代理商进行日统计…