LeetCode——回溯篇(三)

这篇具有很好参考价值的文章主要介绍了LeetCode——回溯篇(三)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

刷题顺序及思路来源于代码随想录,网站地址: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"] 相比就更小,排序更靠前。

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

LeetCode——回溯篇(三),做题总结,leetcode,算法,java,回溯,backtracking

 

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' 和 '.' 分别代表了皇后和空位。

LeetCode——回溯篇(三),做题总结,leetcode,算法,java,回溯,backtracking

 

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 宫内只能出现一次。(请参考示例图)

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

LeetCode——回溯篇(三),做题总结,leetcode,算法,java,回溯,backtracking


/**
 * @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;
	}
}

 文章来源地址https://www.toymoban.com/news/detail-683625.html

到了这里,关于LeetCode——回溯篇(三)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法学习——LeetCode力扣回溯篇2

    40. 组合总和 II - 力扣(LeetCode) 描述 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含重复的组合。 示例 示例 1: 输入: candidates = [10,1,2,7

    2024年02月20日
    浏览(36)
  • 【leetcode刷题之路】剑指Offer(3)——搜索与回溯算法

    7 搜索与回溯算法 7.1 【BFS】剑指 Offer 32 - I - 从上到下打印二叉树 https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/   这里借助队列来实现广度优先遍历,由于需要访问每一层的节点,而且这一层访问才可以访问下一层,所以可以考虑队列的先进先出,先把每一层的节

    2024年02月13日
    浏览(59)
  • leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

    我的往期文章: leetCode 647.回文子串 动态规划 + 优化空间 / 中心扩展法 + 双指针-CSDN博客 https://blog.csdn.net/weixin_41987016/article/details/133883091?spm=1001.2014.3001.5501 leetCode 131.分割回文串 + 回溯算法 + 图解 + 笔记-CSDN博客 https://blog.csdn.net/weixin_41987016/article/details/134700907?spm=1001.2014.3001

    2024年02月05日
    浏览(56)
  • 代码随想录Day20 回溯算法 LeetCode77 组合问题

    以下内容更详细解释来自于:代码随想录 (programmercarl.com) 回溯法也叫回溯搜索法,是搜索法的一种,我们之前在二叉树中也经常使用到回溯来解决问题,其实 有递归就有回溯 ,有的时候回溯隐藏在递归之下,我们不容易发觉,今天我们来详细介绍一下什么是回溯,它能解决哪些问题.

    2024年02月08日
    浏览(54)
  • 算法沉淀——穷举、暴搜、深搜、回溯、剪枝综合练习一(leetcode真题剖析)

    题目链接:https://leetcode.cn/problems/permutations/ 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 示例 2: 示例 3: 提示: 1 = nums.length = 6 -10 = nums[i] = 10 nums 中的所有整数 互不相同 思路 这是一个典型的回溯问题,需要在每

    2024年02月21日
    浏览(71)
  • LeetCode算法题解(回溯)|39. 组合总和、40. 组合总和 II、131. 分割回文串

    题目链接:39. 组合总和 题目描述: 给你一个  无重复元素  的整数数组  candidates  和一个目标整数  target  ,找出  candidates  中可以使数字和为目标数  target  的 所有   不同组合  ,并以列表形式返回。你可以按  任意顺序  返回这些组合。 candidates  中的  同一个  数

    2024年02月05日
    浏览(62)
  • 【数据结构】回溯算法公式化解题 leetcode经典题目带刷:全排列、组合、子集

    一、什么是回溯算法 回溯算法(Backtracking Algorithm)是一种解决 组合问题 、 排列问题 、 选择问题 等一类问题的常用算法。它通过尝试所有可能的选择来找到问题的解,当发现当前选择不符合要求时,就回溯到之前的状态,然后尝试其他的选择。 1、基本思想: 从问题的起

    2024年02月11日
    浏览(45)
  • 【Leetcode60天带刷】day27回溯算法——39. 组合总和,40.组合总和II,131.分割回文串

    ​ 39. 组合总和 给你一个  无重复元素  的整数数组  candidates  和一个目标整数  target  ,找出  candidates  中可以使数字和为目标数  target  的 所有   不同组合  ,并以列表形式返回。你可以按  任意顺序  返回这些组合。 candidates  中的  同一个  数字可以  无限制重复

    2024年02月11日
    浏览(46)
  • leetcode做题笔记58

    给你一个字符串  s ,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中  最后一个  单词的长度。 单词  是指仅由字母组成、不包含任何空格字符的最大子字符串。 本题要求最后一个单词长度,只需从后向前遍历,ans不断增加,一旦遇到空格则输出ans的值 本

    2024年02月14日
    浏览(44)
  • leetcode做题笔记45

    给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处: 0 = j = nums[i]  i + j n 返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。

    2024年02月15日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包