回溯 组合 排列 生成 LeetCode

2023-05-16

回溯 组合 排列 生成 算法题目

77. 组合

给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。

示例:

输入: n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

解法1: 回溯 递归

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        if k > n:
            return []
        if k == n:  # 可以减少运行时间
            return [list(range(1, n+1))]
        # 回溯
        result = []
        def huisu(start, temp):
            if len(temp) == k:
                result.append(temp.copy()) # 特别小心,必须使用copy(浅copy)) 或 深copy
                return 
            for i in range(start, n+1):
                temp.append(i)  # 回溯
                huisu(i+1, temp)  
                temp.pop()
            return 
        huisu(1, [])
        return result

39. 组合总和

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。

示例 1:

输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
  [7],
  [2,2,3]
]

解法1: 回溯 递归

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        result = []
        def digui(target, target_list):
            for item in candidates:
                if target - item == 0:  # 可以相等记录下来
                    tem = target_list+[item]
                    if sorted(tem) not in result:  #  去重复 
                        result.append(sorted(tem))
                elif target - item > 0:
                    digui(target-item, target_list+[item]) # 传参时, 不要加进去
                else:
                    pass
        digui(target, [])
        return result

46. 全排列

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

解法1: 递归

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        # global out
        
        def digui(numlist, S=[]):
            if len(S) == n:
                out.append(S)
                return 
            for i in range(len(numlist)): # 递归+回溯
                digui(numlist[:i] + numlist[i+1:], S+[numlist[i]])
            return 
        out = []
        n = len(nums)
        digui(nums, [])
        return out

全排列 II

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

示例 1:

输入:nums = [1,1,2]
输出:
[[1,1,2],
 [1,2,1],
 [2,1,1]]

解法1: 全排列 + 去重复; 968ms

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        def digui(numlist, S=[]):
            if len(S) == n:
                if S not in out:  # 去重复,费时
                    out.append(S)
                return 
            for i in range(len(numlist)): # 递归+回溯
                digui(numlist[:i] + numlist[i+1:], S+[numlist[i]])
            return 
        out = []
        n = len(nums)
        digui(nums, [])
        return out

解法2: 排序 + 递归 + 去重复; 52 ms

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        nums.sort() # 加一次排序
        n = len(nums)
        res = []
        def digui(nums, temp):
            if len(temp) == n:
                res.append(temp) # 没加copy,因为temp不是直接传递过来的;
                return 
            for i in range(len(nums)):
                if i+1 < len(nums) and nums[i] == nums[i+1]: # 去重复
                    continue
                digui(nums[:i]+nums[i+1:], temp + [nums[i]])
        
        digui(nums, [])
        return res

31. 下一个排列 **

实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。

优秀题解

示例 1:

输入:nums = [1,2,3,4,6,5]
输出:[1,2,3,5,4,6]

解法1:

123456
123465
123546
...
654321
class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # “下一个排列”的定义是:给定数字序列的字典序中下一个更大的排列。
        # 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。 
        i = len(nums) - 2
        while 0 <= i and nums[i] >= nums[i+1]:  # 找到 第一个nums[i] < nums[i+1]
            i = i - 1
        if i >= 0:
            j = len(nums) - 1
            while j >= 0 and nums[i] >= nums[j]: # 最靠右的大于nums[i]
                j = j - 1
            nums[i], nums[j] = nums[j], nums[i] # 互换
    
        left = i + 1
        right = len(nums) - 1
        while left < right:  # 左右互换, 因为i右边是降序排列了,互换后就是升序;
            nums[left], nums[right] = nums[right], nums[left]
            left += 1
            right -= 1
        
        return nums

267. 回文排列 II

给定一个字符串 s ,返回其通过重新排列组合后所有可能的回文字符串,并去除重复的组合。

如不能形成任何回文排列时,则返回一个空列表。

示例 1:

输入: "aabb"
输出: ["abba", "baab"]

示例 2:

输入: "abc"
输出: []

解法1:

class Solution:
    def generatePalindromes(self, s: str) -> List[str]:
        # 1. 要生成 所有 可能的 回文字符串, 判断是否为回文串,超时
        # 2. 判断是否可以构成, 若可以, 使用一半元素,生成所有不重复排列,反转;奇数字符放中间;  可行
        s_dict = {}
        for item in s:
            if item not in s_dict:
                s_dict[item] = 1
            else:
                s_dict[item] += 1
        # print(s_dict)
        odd_count = 0  # 统计奇数字符个数
        odd_str = ""  # 记录是哪个奇数字符
        new_s_dict = {}
        for k, v in s_dict.items():
            if v % 2 != 0:
                odd_count += 1
                if odd_count > 1:
                    return []
                else:
                    new_s_dict[k] =  (v-1) // 2
                    odd_str = k
            else:
                new_s_dict[k] = v // 2
        # 使用一半字母 生成所有可能的 情况
        proce_str = "" 
        for k, v in new_s_dict.items():
            proce_str += k*v
        # print(proce_str)
        # print(odd_str)
        res_temp = []
        n = len(proce_str)
        def digui(strs, temp=""): # 生成所有可能的排列
            if len(temp) == n:
                res_temp.append(temp)
                return 
            for i in range(len(strs)):
                if i+1<len(strs) and strs[i]==strs[i+1]:
                    continue
                digui(strs[:i]+strs[i+1:], temp+strs[i])
            return 
        digui(proce_str, "")  
        # print(res_temp)
        new_res = []
        for item in res_temp: # 每种可能+奇数字符+每种可能的倒序
            new_res.append(item+odd_str+item[::-1])
        return new_res
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

回溯 组合 排列 生成 LeetCode 的相关文章

  • day7: 剑指 Offer 44. 数字序列中某一位的数字

    1 剑指 Offer 44 数字序列中某一位的数字 数字以0123456789101112131415 的格式序列化到一个字符序列中 在这个序列中 xff0c 第5位 xff08 从下标0开始计数 xff09 是5 xff0c 第13位是1
  • casbin 使用说明记录

    本文简单记录casbin 安装步骤 使用 Casbin 作为 ThinkPHP 的权限控制中间件 PHP Casbin 是一个强大的 高效的开源访问控制框架 xff0c 它支持基于各种访问控制模型的权限管理 Think Casbin 是一个
  • 844. 比较含退格的字符串

    给定 S 和 T 两个字符串 xff0c 当它们分别被输入到空白的文本编辑器后 xff0c 判断二者是否相等 xff0c 并返回结果 代表退格字符 注意 xff1a 如果对空文本输入退格字符 xff0c 文本继续为空 示例 1 xff1a

随机推荐

  • 笔试题记录

    1 逆波兰表达式 是称为 后缀表达式 xff0c 把运算量写在前面 xff0c 把算符写在后面 写出a b c d 43 e f g h 43 i j k 的逆波兰表达式 拆开写各个部分的 xff1a 按优先级 xff08 1 xff09
  • 牛客网 赛码在线编程中数据读取问题

    一 数据读取的方式 xff08 python3 xff09 1 input 读取输入数据 while True try inputs 61 input except break 2 网站的数据输入是是一个含有多行数据的input文件 in文
  • 贪心算法 leetcode编程题

    1 452 用最少数量的箭引爆气球 在二维空间中有许多球形的气球 对于每个气球 xff0c 提供的输入是水平方向上 xff0c 气球直径的开始和结束坐标 由于它是水平的 xff0c 所以纵坐标并不重要 xff0c 因此只要知道开始和结束的横
  • 排序题 LeetCode题

    1 1370 上升下降字符串 给你一个字符串 s xff0c 请你根据下面的算法重新构造字符串 xff1a 从 s 中选出 最小 的字符 xff0c 将它 接在 结果字符串的后面 从 s 剩余字符中选出 最小 的字符 xff0c 且该字符比
  • BP算法公式推导

    令表示第层的第个神经元到第层的第个神经元的连接权值 xff0c 表示第层第个神经元的输入 xff0c 表示第层第个神经元的输出 xff0c 表示层第个神经元的偏置 xff0c C表示代价函数 则有 xff1a 其中 表示激活函数 训练多层网
  • 卷积神经网络中的Separable Convolution_转载

    卷积神经网络在图像处理中的地位已然毋庸置疑 卷积运算具备强大的特征提取能力 相比全连接又消耗更少的参数 xff0c 应用在图像这样的二维结构数据中有着先天优势 然而受限于目前移动端设备硬件条件 xff0c 显著降低神经网络的运算量依旧是网络
  • 二分查找方法 leetcode题

    这里用来 记录 使用二分查找方法 的题目 1 704 二分查找 给定一个 n 个元素有序的 xff08 升序 xff09 整型数组 nums 和一个目标值 target xff0c 写一个函数搜索 nums 中的 target xff0c
  • 动态规划题 leetcode

    1 62 不同路径 一个机器人位于一个 m x n 网格的左上角 xff08 起始点在下图中标记为 Start xff09 机器人每次只能向下或者向右移动一步 机器人试图达到网格的右下角 xff08 在下图中标记为 Finish xff09
  • 字典序 Leetcode题目

    1 440 字典序的第K小数字 给定整数 n 和 k xff0c 找到 1 到 n 中字典序第 k 小的数字 注意 xff1a 1 k n 109 示例 xff1a 输入 n 13 k 2 输出 10 解释 字典序的排列是 1 10 11
  • Git:从Git下载项目到本地及项目重建

    从Git上下载项目 重建项目
  • 子序列题目 Leetcode题目

    1 53 最大子序和 面试题 16 17 连续数列 给定一个整数数组 nums xff0c 找到一个具有最大和的连续子数组 xff08 子数组最少包含一个元素 xff09 xff0c 返回其最大和 示例 xff1a 输入 2 1 3 4 1
  • 整数问题(求和 拆分 替换等) leetcode问题

    1 829 连续整数求和 给定一个正整数 N xff0c 试求有多少组连续正整数满足所有数字之和为 N 示例 1 输入 5 输出 2 解释 5 61 5 61 2 43 3 xff0c 共有两组连续整数 5 2 3 求和后为 5 示例 2
  • B 中等题 LeetCode

    中等题 按出题指数排列 1 2 两数相加 给出两个 非空 的链表用来表示两个非负的整数 其中 xff0c 它们各自的位数是按照 逆序 的方式存储的 xff0c 并且它们的每个节点只能存储 一位 数字 如果 xff0c 我们将这两个数相加起来
  • 回文串 leetcode

    1 125 验证回文串 给定一个字符串 xff0c 验证它是否是回文串 xff0c 只考虑字母和数字字符 xff0c 可以忽略字母的大小写 说明 xff1a 本题中 xff0c 我们将空字符串定义为有效的回文串 示例 1 输入 34 A m
  • 回溯法 题目 leetcode

    1 22 括号生成 数字 n 代表生成括号的对数 xff0c 请你设计一个函数 xff0c 用于能够生成所有可能的并且 有效的 括号组合 示例 xff1a 输入 xff1a n 61 3 输出 xff1a 34 34 34 34 34 34
  • 买卖股票系列问题 Leetcode题目

    leetcode 刷题记录 一 买卖股票系列问题 1 121 买卖股票的最佳时机 给定一个数组 xff0c 它的第 i 个元素是一支给定股票第 i 天的价格 如果你最多只允许完成一笔交易 xff08 即买入和卖出一支股票一次 xff09 x
  • 区间问题 LeetCode

    表示重点复习题 xff0c 没做出来 区间问题 1 56 合并区间 给出一个区间的集合 xff0c 请合并所有重叠的区间 示例 1 输入 intervals 61 1 3 2 6 8 10 15 18 输出 1 6 8 10 15 18 解
  • 网格DFS LeetCode

    岛屿问题 DFS 200 岛屿数量 给你一个由 1 xff08 陆地 xff09 和 0 xff08 水 xff09 组成的的二维网格 xff0c 请你计算网格中岛屿的数量 岛屿总是被水包围 xff0c 并且每座岛屿只能由水平方向和 或竖直
  • 括号题目 Leetcode

    括号系列问题 Leetcode 20 有效的括号 给定一个只包括 39 39 xff0c 39 39 xff0c 39 39 xff0c 39 39 xff0c 39 39 xff0c 39 39 的字符串 s xff0c 判断字符串是否有
  • 回溯 组合 排列 生成 LeetCode

    回溯 组合 排列 生成 算法题目 77 组合 给定两个整数 n 和 k xff0c 返回 1 n 中所有可能的 k 个数的组合 示例 输入 n 61 4 k 61 2 输出 2 4 3 4 2 3 1 2 1 3 1 4 解法1 回溯 递归