LeetCode——回溯篇(三)

news2024/9/19 22:19:38

刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com

目录

46. 全排列

47. 全排列 II

332. 重新安排行程

51. N 皇后

37. 解数独


 

46. 全排列

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

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author light
 * @Description 全排列
 * @create 2023-08-30 9:36
 */
public class PermuteTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int n=input.nextInt();
		int[] nums=new int[n];
		for (int i = 0; i < n; i++) {
			nums[i]=input.nextInt();
		}
		System.out.println(permute(nums));
	}
	public static List<List<Integer>> res=new ArrayList<>();
	public static List<Integer> path=new ArrayList<>();
	public static List<List<Integer>> permute(int[] nums) {
		int[] used=new int[nums.length]; //记录数组中哪个元素已经使用过了
		Arrays.fill(used,0);
		backtracking(nums,used);
		return res;
	}

	private static void backtracking(int[] nums,int[] used) {
		if(path.size()==nums.length){
			res.add(new ArrayList<>(path));
			return;
		}
		for (int i = 0; i < nums.length; i++) {
			if(used[i]==0){
				path.add(nums[i]);
				used[i]=1;
				backtracking(nums,used);
				//回溯
				path.remove(path.size()-1);
				used[i]=0;
			}
		}
	}
}

47. 全排列 II

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

输入:nums = [1,1,2]
输出:
[[1,1,2],
 [1,2,1],
 [2,1,1]]
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author light
 * @Description 全排列II
 *
 *给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
 *
 * (需要去重
 * @create 2023-08-30 9:59
 */
public class PermuteUniqueTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int n=input.nextInt();
		int[] nums=new int[n];
		for (int i = 0; i < n; i++) {
			nums[i]=input.nextInt();
		}
		System.out.println(permuteUnique(nums));
	}

	public static List<List<Integer>> res=new ArrayList<>();
	public static List<Integer> path=new ArrayList<>();

	public static List<List<Integer>> permuteUnique(int[] nums) {
		Arrays.sort(nums);
		int[] used=new int[nums.length]; //记录数组中哪个元素已经使用过了--同时去重
		Arrays.fill(used,0);
		backtracking(nums,used);
		return  res;
	}

	private static void backtracking(int[] nums, int[] used) {
		if(path.size()== nums.length){
			res.add(new ArrayList<>(path));
			return;
		}
		for (int i = 0; i < nums.length; i++) {
			//去重逻辑
			if(i>0&&nums[i]==nums[i-1]&&used[i-1]==0){
				continue;
			}
			if(used[i]==0){ //数组元素还未使用
				path.add(nums[i]);
				used[i]=1;
				backtracking(nums,used);
				//回溯
				path.remove(path.size()-1);
				used[i]=0;
			}
		}
	}
}

332. 重新安排行程

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

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

  • 例如,行程 ["JFK", "LGA"] 与 ["JFK", "LGB"] 相比就更小,排序更靠前。

假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。

 

public class FindItineraryTest {

	public LinkedList<String> res;
	public LinkedList<String> path=new LinkedList<>();

	public List<String> findItinerary(List<List<String>> tickets) {
		//对集合中元素降落地点排序
		Collections.sort(tickets, new Comparator<List<String>>() {
			@Override
			public int compare(List<String> o1, List<String> o2) {
				return o1.get(1).compareTo(o2.get(1));
			}
		});
		path.add("JFK"); //从JFK出发
		boolean[] used=new boolean[tickets.size()]; //判断元素是否重复
		Arrays.fill(used,false);
		backtracking((ArrayList)tickets,used);
		return res;
	}

	private boolean backtracking(ArrayList<List<String>> tickets, boolean[] used) {
		//终止条件
		if(path.size()==tickets.size()+1){
			res=new LinkedList<>(path);  //只有一条路径
			return true;
		}

		for (int i = 0; i < tickets.size(); i++) {
			//未使用重复元素并且path中最后一个元素的值等于tickets数组航班中的起飞航班,则将降落航班加入path中
			if(!used[i]&&tickets.get(i).get(0).equals(path.getLast())){
				path.add(tickets.get(i).get(1));
				used[i]=true;
				if(backtracking(tickets,used)){
					return true;
				}
				//回溯
				used[i]=false;
				path.removeLast();
			}

		}
		return false;
	}

}

51. N 皇后

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author light
 * @Description N皇后
 * @create 2023-08-30 11:13
 */
public class SolveNQueensTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int n=input.nextInt();
		System.out.println(solveNQueens(n));
	}


	public static List<List<String>> res=new ArrayList<>();

	public static List<List<String>> solveNQueens(int n) {
		char[][] chessboard = new char[n][n];
		for (char[] c : chessboard) {
			Arrays.fill(c, '.');
		}
		backtracking(chessboard,n,0);
		return res;
	}

	//row:行--控制递归深度
	private static void backtracking(char[][] chessboard, int n, int row) {
		//终止条件--收获结果
		if(row==n){
			res.add(arrayToList(chessboard));
			return;
		}
		//单层递归逻辑
		for (int col = 0; col < n; col++) {
			//判断是否合法位置
			if(isValid(chessboard,row,col,n)){
				chessboard[row][col]='Q';
				backtracking(chessboard,n,row+1);
				//回溯
				chessboard[row][col]='.';
			}
		}
	}

	private static List<String> arrayToList(char[][] chessboard) {
		List<String> path=new ArrayList<>();
		for (int i = 0; i < chessboard.length; i++) {
			path.add(String.valueOf(chessboard[i]));
		}
		return path;
	}

	/*
	验证棋盘是否合法
		按照如下标准去重:
			1.不能同行
			2.不能同列
			3.不能同斜线 (45度和135度角)
	 */
	private static boolean isValid(char[][] chessboard, int row, int col, int n) {
		检查行  (可以不用检查行,每一次递归,row+1
		//for (int i = 0; i < col; i++) {
		//	if(chessboard[row][i]=='Q'){
		//		return false;
		//	}
		//}

		//检查列
		for (int i = 0; i < row; i++) {
			if(chessboard[i][col]=='Q'){
				return  false;
			}
		}

		//检查斜线--45度
		for (int i = row-1,j=col-1; i>=0&&j>=0 ; i--,j--) {
			if(chessboard[i][j]=='Q'){
				return  false;
			}
		}

		//检查斜线--135度
		for (int i = row-1,j=col+1; i >=0&&j<n ; i--,j++) {
			if(chessboard[i][j]=='Q'){
				return false;
			}
		}

		return true;

	}

}

37. 解数独

编写一个程序,通过填充空格来解决数独问题。

数独的解法需 遵循如下规则

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 '.' 表示。


/**
 * @author light
 * @Description 解数独
 *
 * @create 2023-08-30 12:19
 */
public class SolveSudokuTest {
	public static void solveSudoku(char[][] board) {
		backtracking(board);
	}

	private static boolean backtracking(char[][] board) {

		for (int i = 0; i < 9; i++) { //行
			for (int j = 0; j < 9; j++) { //列
				if(board[i][j]!='.'){
					continue;
				}else {

					for (char k = '1'; k <='9' ; k++) {
						if(isValid(i,j,k,board)){
							board[i][j]=k;
							if(backtracking(board)){
								return true;
							}
							//回溯
							board[i][j]='.';
						}
					}
					// 9个数都试完了,都不行,那么就返回false
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 判断棋盘是否合法有如下三个维度:
	 *     同行是否重复
	 *     同列是否重复
	 *     9宫格里是否重复
	 */
	private static boolean isValid(int row, int col, char val,char[][] board) {
		//同行是否重复
		for (int i = 0; i < 9; i++) {
			if(board[row][i]==val){
				return false;
			}
		}

		//同列是否重复
		for (int i = 0; i <9; i++) {
			if(board[i][col]==val){
				return false;
			}
		}

		//9宫格里是否重复
		int startRow=(row/3)*3;
		int startCol=(col/3)*3;
		for (int i = startRow; i <startRow+3 ; i++) {
			for (int j = startCol; j < startCol+3; j++) {
				if(board[i][j]==val){
					return false;
				}
			}
		}
		return true;
	}
}

 

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

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

相关文章

uni-app实现点击显示隐藏列表,兼容微信小程序

效果&#xff1a; <view class"list-item" v-for"(item,index1) in listData" :key"index1"><view class"item-title" click"item.content.length>0?handleToggle(item,index1):"><view class"&qu…

Ansible学习笔记7

user模块&#xff1a; user模块用于管理用户账户和用户属性。 如果是windows要换一个win_user模块。 创建用户&#xff1a;present&#xff1a; [rootlocalhost ~]# ansible group1 -m user -a "nameaaa statepresent" 192.168.17.106 | CHANGED > {"ansi…

链表(详解)

一、链表 1.1、什么是链表 1、链表是物理存储单元上非连续的、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表的指针地址实现&#xff0c;有一系列结点&#xff08;地址&#xff09;组成&#xff0c;结点可动态的生成。 2、结点包括两个部分&#xff1a;&#x…

骨传导耳机有什么副作用? 骨传导耳机对身体有损伤吗

根据目前的科学研究和经验&#xff0c;骨传导耳机被认为是相对安全的使用设备&#xff0c;不会引起副作用&#xff0c;也不会对身体造成损伤&#xff0c;相比会对我们的耳朵听力起到一定的保护作用。 但是&#xff0c;个体差异和特殊情况可能会影响人们对骨传导耳机的感受与反应…

成集云 | 抖店客户静默下单催付数据同步钉钉 | 解决方案

源系统成集云目标系统 方案介绍 随着各品牌全渠道铺货&#xff0c;主播在平台上直播时客户下了订单后不能及时付款&#xff0c;第一时间客户收不到提醒&#xff0c;不仅造成了客户付款率下降&#xff0c;更大量消耗了企业的人力成本和经济。而成集云与钉钉深度合作&#xff0…

【C++实战】C++实现贪吃蛇(含源代码)—基于easyx图形库

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f340;本文前置知识&#xff1a;C基础 ♈️今日夜电波&#xff1a;toge—あよ 0:36 ━━━━━━️&#x1f49f;──────── 4:03 &a…

springboot整合jquery实现前后端数据交互

一 实施逻辑 1.1 前端 <!doctype html> <html lang"en"><head><meta charset"UTF-8"><meta name"Generator" content"EditPlus"><meta name"Author" content""><meta n…

Centos7 |Canal Admin搭建Canal Server集群|

一: 使用CanalAdmin来搭建一个canal集群 1.1 环境规划 服务名称|主机节点 机器IP 节点 备注 canal admin | docker0 192.168.1.100 192.168.1.100:8888 canal admin 机器 canal server 1 | docker1 192.168.1.101 192.168.1.100:8888 canal se…

Kafka3.0.0版本——Leader Partition自动平衡

目录 一、Leader Partition自动平衡的概述二、Leader Partition自动平衡的相关配置参数三、Leader Partition自动平衡的示例 一、Leader Partition自动平衡的概述 正常情况下&#xff0c;Kafka本身会自动把Leader Partition均匀分散在各个机器上&#xff0c;来保证每台机器的读…

Mac“其他文件”存放着什么?“其他文件”的清理方法

很多Mac用户在清理磁盘空间时发现&#xff0c;内存占用比例比较大的除了有iCloud云盘、应用程序、影片、音频、照片等项目之外&#xff0c;还有一个“其他文件”的项目磁盘占用比也非常大&#xff0c;想要清理却无从下手。那么Mac“其他文件”里存放的是什么文件&#xff1f;我…

HBuilderX修改manifest.json设置,解决跨域问题(CORS、Cross-Origin)

搭建一个前台uniapp&#xff0c;后台springboot的开发环境时&#xff0c;遇到了跨域问题。 console提示错误信息&#xff1a; Access to XMLHttpRequest at http://10.0.180.203/api/cms/getAdList?apId1 from origin http://localhost:8080 has been blocked by CORS policy…

常用框架分析(7)-Flutter

框架分析&#xff08;7&#xff09;-Flutter 专栏介绍Flutter核心思想Flutter的特点快速开发跨平台高性能美观的用户界面 Flutter的架构框架层引擎层平台层 开发过程使用Dart语言编写代码编译成原生代码热重载工具和插件 优缺点优点跨平台开发高性能美观的用户界面热重载强大的…

pinia——添加插件——基础积累

问题&#xff1a;是否给pinia添加过插件&#xff1f;具体添加的方式是什么&#xff1f; 在pinia中&#xff0c;我们可以为仓库添加插件&#xff0c;通过添加插件能够扩展以下的内容&#xff1a; 为 store 添加新的属性 定义 store 时增加新的选项 为 store 增加新的方法 包装现…

怎么传输大文件跨国,如何跨国快速传输大文件

在当前数字化时代的背景下&#xff0c;跨国传输大文件已经成为企业和个人工作中不可避免的挑战。尽管存在技术障碍和阻碍&#xff0c;但借助先进的技术和服务&#xff0c;我们仍能高效完成跨国大文件传输任务。接下来将介绍几种常见的跨国快速传输大文件的方法。 一、FTP文件传…

固定资产台账怎么管理

固定资产台账是指企业对固定资产进行登记、分类、统计和管理的账簿。固定资产管理系统是一款专业的固定资产管理软件&#xff0c;可以帮助企业实现资产全生命周期管理&#xff0c;包括资产采购、入库、领用、归还、维修、报废等环节。系统具有实时监控、预警提醒、报表分析等功…

PostgreSQL数据导入导出【亲测】有图有真相

pg_dump是用于备份PostgreSQL数据库的工具。它可以在数据库正在使用的时候进行完整一致的备份&#xff0c;并不阻塞其它用户对数据库的访问。 有图有真相 文章目录 导出导入压缩方法 导出 pg_dump -h 127.0.0.1 -p 5432 -U readuser mydatabase > dum.sql导入 1、导入整个…

函数和方法回顾、cbv源码分析、APIView执行流程分析、序列化组件介绍、序列化组件快速使用之序列化、常用字段类和参数、序列化组件之校验

一 函数和方法回顾 函数和方法-函数:使用def关键字定义的函数,有几个参数&#xff0c;就要传几个参数&#xff0c;不能多&#xff0c;不能少-----》按位置传&#xff0c;按关键字传-方法&#xff1a;定义在类内部&#xff0c;可以自动传值的函数称之为方法---》绑定给对象的方…

vue3+ts+tinynce在富文本编辑器菜单栏实现下拉框选择

实现效果 代码&#xff1a; <script lang"ts" setup> import Editor from tinymce/tinymce-vue import tinymce from tinymce; import { getIndicator } from /api/data-assets/data-dictoryimport {computed, ref} from "vue"; const props defin…

Linux centos7 bash编程——-求质数和

训练项目&#xff1a;使用函数求质数和。 定义一个函数IsPrime()&#xff0c;据此判断一个数是否为质数 由用户输入一个整数&#xff0c;求出比此数大的两个最小质数之和。 一、解决思路: 1.先在键盘上输入一个整数 2.求出比此数大的最小质数 3.再求出比此质数大的另一个…