您的位置:首页 > 健康 > 美食 > 大型门户网站建设效果怎么样_牡丹江疫情最新消息_搜易网优化的效果如何_sem搜索引擎营销是什么

大型门户网站建设效果怎么样_牡丹江疫情最新消息_搜易网优化的效果如何_sem搜索引擎营销是什么

2024/12/23 15:28:12 来源:https://blog.csdn.net/T_Y_F_/article/details/143955032  浏览:    关键词:大型门户网站建设效果怎么样_牡丹江疫情最新消息_搜易网优化的效果如何_sem搜索引擎营销是什么
大型门户网站建设效果怎么样_牡丹江疫情最新消息_搜易网优化的效果如何_sem搜索引擎营销是什么

要从给定的 m 个数 中生成 n 个数的所有组合,我们可以使用递归或迭代方法,具体解决过程如下:


1. 问题说明

给定一个大小为 m 的数组,例如 [1, 2, 3],生成所有长度为 n 的组合(可以包括重复数字,也可以不包括)。

两种组合方式:

  1. 组合(不允许重复):

    • 每个数字只能使用一次。
    • 如果 n > m,则没有解。
    • 示例:从 [1, 2, 3] 中选出长度为 2 的组合,结果为:[1, 2], [1, 3], [2, 3]
  2. 带重复的组合(允许重复):

    • 每个数字可以被重复使用。
    • 示例:从 [1, 2, 3] 中选出长度为 2 的组合,结果为:[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]

2. 实现方案

2.1 不允许重复的组合

算法思路
  • 使用递归来构造结果。
  • 每次选择一个数字后,不能再选择它(避免重复)。
  • 当选够了 n 个数字 时,将结果加入最终答案。
实现代码
import java.util.ArrayList;
import java.util.List;public class Combinations {public static List<List<Integer>> generateCombinations(int[] nums, int n) {List<List<Integer>> result = new ArrayList<>();backtrack(nums, n, 0, new ArrayList<>(), result);return result;}private static void backtrack(int[] nums, int n, int start, List<Integer> current, List<List<Integer>> result) {// 如果组合长度达到目标 n,添加到结果中if (current.size() == n) {result.add(new ArrayList<>(current));return;}// 从 start 开始,依次选择数字for (int i = start; i < nums.length; i++) {current.add(nums[i]); // 选择当前数字backtrack(nums, n, i + 1, current, result); // 递归选择剩余的数字current.remove(current.size() - 1); // 回溯}}public static void main(String[] args) {int[] nums = {1, 2, 3};int n = 2;List<List<Integer>> combinations = generateCombinations(nums, n);System.out.println(combinations); // 输出: [[1, 2], [1, 3], [2, 3]]}
}
运行流程
  • 假设输入数组为 [1, 2, 3],目标组合长度为 2:
    1. 1 开始,递归选择 23,生成 [1, 2][1, 3]
    2. 2 开始,递归选择 3,生成 [2, 3]
    3. 最终结果为:[[1, 2], [1, 3], [2, 3]]

2.2 允许重复的组合

算法思路
  • 使用递归来构造结果。
  • 每次选择一个数字后,仍然可以选择它(允许重复)。
  • 当选够了 n 个数字 时,将结果加入最终答案。
实现代码
import java.util.ArrayList;
import java.util.List;public class CombinationsWithRepetition {public static List<List<Integer>> generateCombinations(int[] nums, int n) {List<List<Integer>> result = new ArrayList<>();backtrack(nums, n, 0, new ArrayList<>(), result);return result;}private static void backtrack(int[] nums, int n, int start, List<Integer> current, List<List<Integer>> result) {// 如果组合长度达到目标 n,添加到结果中if (current.size() == n) {result.add(new ArrayList<>(current));return;}// 从 start 开始,依次选择数字(可以重复选择)for (int i = start; i < nums.length; i++) {current.add(nums[i]); // 选择当前数字backtrack(nums, n, i, current, result); // 递归选择剩余的数字(允许重复)current.remove(current.size() - 1); // 回溯}}public static void main(String[] args) {int[] nums = {1, 2, 3};int n = 2;List<List<Integer>> combinations = generateCombinations(nums, n);System.out.println(combinations); // 输出: [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]}
}
运行流程
  • 假设输入数组为 [1, 2, 3],目标组合长度为 2:
    1. 1 开始,递归选择 1, 2, 3,生成 [1, 1], [1, 2], [1, 3]
    2. 2 开始,递归选择 2, 3,生成 [2, 2], [2, 3]
    3. 3 开始,递归选择 3,生成 [3, 3]
    4. 最终结果为:[[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]

3. 时间复杂度分析

  1. 不允许重复的组合:

    • 假设数组大小为 m,组合长度为 n
    • 时间复杂度为 O ( C ( m , n ) ) = O ( m ! n ! ( m − n ) ! ) O(C(m, n)) = O(\frac{m!}{n!(m-n)!}) O(C(m,n))=O(n!(mn)!m!),因为每种组合只会生成一次。
  2. 允许重复的组合:

    • 时间复杂度为 O ( m n ) O(m^n) O(mn),因为每个位置可以选择 m 种数字,共有 n 个位置。

4. 示例测试

4.1 不允许重复的组合

  • 输入:nums = [1, 2, 3], n = 2
  • 输出:[[1, 2], [1, 3], [2, 3]]

4.2 允许重复的组合

  • 输入:nums = [1, 2, 3], n = 2
  • 输出:[[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]

5. 总结

特性不允许重复的组合允许重复的组合
是否允许重复选取
时间复杂度 O ( C ( m , n ) ) O(C(m, n)) O(C(m,n)) O ( m n ) O(m^n) O(mn)
适用场景选择独特的对象,避免重复允许重复选择的对象,例如排列、带放回的抽取。

动态规划或递归回溯是生成组合的常见方法,根据问题需求选择适合的实现方式。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com