算法每日一练 (13)

欢迎来到张胤尘的技术站
技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌

文章目录

  • 算法每日一练 (13)
    • 全排列 II
      • 题目描述
      • 解题思路
      • 解题代码
        • `c/c++`
        • `golang`
        • `lua`

官方站点: 力扣 Leetcode

算法每日一练 (13)

全排列 II

题目地址:全排列 II

题目描述

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

解题思路

  • 整体解题流程采用回溯的思路。
  • 首先递归终止条件,如果当前状态已经满足了子集的条件,则返回到上一层。在本题中,递归终止条件就是当前索引到达了数组末尾,则无需向下继续递归。
  • 根据题意 nums 序列中会出现重复项,但是在结果集中不能出现重复的序列,故借助缓存集合 used,在每一层中需要排除已经遍历过的元素。
  • 紧接着就是在递归的过程中,枚举所有可能的选择,并针对每种情况都进行处理。
  • 从当前索引开始,判断元素是否已经在缓存集合 used 中出现,如果出现则直接跳过本次循环。
  • 尝试交换每个位置的元素,然后递归的调用 backtrack 方法处理每一种情况。
  • 接着回溯是关键步骤,在每次递归返回后,需要撤销当前的选择,恢复到上一步的状态,以便尝试其他可能性。
  • 最后当所有的排列全部列举完毕后,返回 result 结果集即可。

解题代码

c/c++
#include 
#include 

class Solution
{
public:
    std::vector<std::vector<int>> permuteUnique(std::vector<int> &nums)
    {
        std::vector<std::vector<int>> result;
        backtrack(result, nums, 0);
        return result;
    }

private:
    void backtrack(std::vector<std::vector<int>> &result, std::vector<int> &current, int start)
    {
        int sz = current.size();
        if (start == sz)
        {
            result.push_back(current);
            return;
        }

        std::unordered_set<int> used;

        for (int i = start; i < sz; i++)
        {
            if (used.find(current[i]) != used.end())
                continue;

            used.insert(current[i]);

            std::swap(current[i], current[start]);
            backtrack(result, current, start + 1);
            std::swap(current[i], current[start]);
        }
    }
};
golang
func permuteUnique(nums []int) [][]int {
	result := [][]int{}
	backtrack(&result, &nums, 0)
	return result
}

func backtrack(result *[][]int, current *[]int, start int) {
	sz := len(*current)

	if start == sz {
		dst := make([]int, sz)
		copy(dst, *current)
		*result = append(*result, dst)
		return
	}

	used := make(map[int]bool)

	for i := start; i < sz; i++ {
		if used[(*current)[i]] {
			continue
		}

		used[(*current)[i]] = true

		(*current)[i], (*current)[start] = (*current)[start], (*current)[i]
		backtrack(result, current, start+1)
		(*current)[i], (*current)[start] = (*current)[start], (*current)[i]
	}
}
lua
local function copyTable(t)
    local copy = {}
    for i = 1, #t do
        table.insert(copy, t[i])
    end
    return copy
end

local function backtrack(result, current, start)
    local sz = #current
    if start == sz then
        table.insert(result, copyTable(current))
        return
    end

    local used = {}

    for i = start, sz do
        if used[current[i]] ~= nil then
            goto continue
        end

        used[current[i]] = i

        current[i], current[start] = current[start], current[i]
        backtrack(result, current, start + 1)
        current[i], current[start] = current[start], current[i]
        ::continue::
    end
end

local function permuteUnique(nums)
    local result = {}
    backtrack(result, nums, 1)
    return result
end

撒花!

如果本文对你有帮助,就点关注或者留个
如果您有任何技术问题或者需要更多其他的内容,请随时向我提问。

在这里插入图片描述

你可能感兴趣的:(算法每日一练,算法,数据结构)