46. 全排列,47. 全排列 II,48. 旋转图像,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.19 可通过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
中的所有整数 互不相同
我们可以定义一个辅助函数来实现回溯。这个函数将维护一个当前的排列path
和一个记录哪些数字已被使用的used
数组。每次递归时,我们遍历nums
数组中的每个数字,如果这个数字尚未被使用,我们就把它添加到当前排列中,并标记为已使用,然后递归调用辅助函数。递归结束后,我们需要撤销当前数字的使用状态,以便进行下一次循环的尝试。
步骤如下:
res
来存储所有可能的全排列。backtrack
,它接受当前路径path
和使用状态数组used
。backtrack
函数中,如果path
的长度等于nums
的长度,说明找到了一个全排列,将其添加到res
中。nums
数组,如果当前元素未被使用,则将其添加到path
中,并标记为已使用,然后递归调用backtrack
。递归返回后,撤销当前元素的使用状态和path
中的元素,以进行下一轮尝试。backtrack
函数开始回溯过程,并返回res
作为所有可能的全排列。class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
def backtrack(path, used):
# 如果当前路径的长度等于 nums 的长度,说明找到了一个全排列
if len(path) == len(nums):
res.append(path[:]) # 深拷贝当前路径到结果列表
return
for i in range(len(nums)):
if not used[i]: # 检查 nums[i] 是否已在当前路径中
path.append(nums[i]) # 添加到路径
used[i] = True # 标记为已使用
backtrack(path, used) # 递归
path.pop() # 回溯,移除路径最后一个元素
used[i] = False # 回溯,标记为未使用
res = [] # 存储所有可能的全排列
backtrack([], [False] * len(nums)) # 初始化路径和使用状态数组
return res
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
backtrack(res, nums, new ArrayList<>(), new boolean[nums.length]);
return res;
}
private void backtrack(List<List<Integer>> res, int[] nums, List<Integer> path, boolean[] used) {
if (path.size() == nums.length) {
res.add(new ArrayList<>(path)); // 添加一种全排列到结果列表
return;
}
for (int i = 0; i < nums.length; i++) {
if (!used[i]) {
path.add(nums[i]); // 添加到路径
used[i] = true; // 标记为已使用
backtrack(res, nums, path, used); // 递归
path.remove(path.size() - 1); // 回溯,移除路径最后一个元素
used[i] = false; // 回溯,标记为未使用
}
}
}
}
给定一个可包含重复数字的序列
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
解决包含重复数字序列的全排列问题,核心思路仍然是使用回溯算法,但需要额外注意如何避免生成重复的排列。为此,我们可以采取以下策略:
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort() # 排序,让相同的数字聚在一起
def backtrack(path, used):
if len(path) == len(nums):
res.append(path[:])
return
for i in range(len(nums)):
# 如果当前数字已被使用,或者与前一个数字相同且前一个数字未被使用,则跳过
if used[i] or (i > 0 and nums[i] == nums[i-1] and not used[i-1]):
continue
used[i] = True
path.append(nums[i])
backtrack(path, used)
used[i] = False
path.pop()
backtrack([], [False] * len(nums))
return res
public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums); // 排序
backtrack(res, nums, new ArrayList<>(), new boolean[nums.length]);
return res;
}
private void backtrack(List<List<Integer>> res, int[] nums, List<Integer> path, boolean[] used) {
if (path.size() == nums.length) {
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) {
continue;
}
used[i] = true;
path.add(nums[i]);
backtrack(res, nums, path, used);
used[i] = false;
path.remove(path.size() - 1);
}
}
}
给定一个 n × n 的二维矩阵
matrix
表示一个图像。请你将图像顺时针旋转 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[[7,4,1],[8,5,2],[9,6,3]]示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]] 输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
将图像顺时针旋转90度,可以通过以下两步完成:
matrix[i][j]
变成matrix[j][i]
。详细步骤:
matrix[i][j]
和matrix[j][i]
进行交换,这样可以得到矩阵的转置。class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
# 转置矩阵
for i in range(n):
for j in range(i, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
# 翻转每一行
for i in range(n):
matrix[i].reverse()
public class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
// 转置矩阵
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// 翻转每一行
for (int i = 0; i < n; i++) {
for (int j = 0, k = n - 1; j < k; j++, k--) {
int temp = matrix[i][j];
matrix[i][j] = matrix[i][k];
matrix[i][k] = temp;
}
}
}
}
更多【算法-力扣热门算法题 46-48】相关视频教程:www.yxfzedu.com