聊聊一个面试中经常出现的算法题:组合运算及其实际应用例子

1 篇文章 0 订阅

image

前言

组合运算是一个数据概念,具体来说,组合运算就是从给定元素集合中选择特定数量的元素进行运算,而不考虑元素的顺序,关注的是哪些元素被选中,而不关心它们的排列顺序。

比如,有一个整数数组 int[] numbers = { 1, 2, 3},它的所有组合就是:

1
2
3
1,2
1,3
2,3
1,2,3

在 C# 中,可以使用递归和循环结构来实现排列组合运算。

简单例子:列出一个整数数组 int[] numbers = { 1, 2, 3, 4 } 的所有组合

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        int[] numbers = { 1, 2, 3, 4 };

        List<List<int>> combinations = GenerateCombinations(numbers);

        foreach (var combination in combinations)
        {
            Console.WriteLine(string.Join(", ", combination));
        }
    }

    static List<List<int>> GenerateCombinations(int[] numbers)
    {
        List<List<int>> result = new List<List<int>>();

        for (int i = 1; i <= numbers.Length; i++)
        {
            GenerateCombinationsUtil(numbers, i, 0, new List<int>(), result);
        }

        return result;
    }

    static void GenerateCombinationsUtil(int[] numbers, int k, int start, List<int> currentCombination, List<List<int>> result)
    {
        if (k == 0)
        {
            result.Add(new List<int>(currentCombination));
            return;
        }

        for (int i = start; i < numbers.Length; i++)
        {
            currentCombination.Add(numbers[i]);
            GenerateCombinationsUtil(numbers, k - 1, i + 1, currentCombination, result);
            currentCombination.RemoveAt(currentCombination.Count - 1);
        }
    }
}

运行后以上代码会生成整数数组 { 1, 2, 3, 4 } 的所有可能组合,并将这些组合打印到控制台。

进阶一:根据需要打印出数组的组合

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        int[] numbers = { 1, 2, 3, 4 };
        int k = 2; // 选择的元素数量

        List<List<int>> combinations = GenerateCombinations(numbers, k);

        foreach (var combination in combinations)
        {
            Console.WriteLine(string.Join(", ", combination));
        }
    }

    static List<List<int>> GenerateCombinations(int[] numbers, int k)
    {
        List<List<int>> result = new List<List<int>>();
        List<int> currentCombination = new List<int>();

        GenerateCombinationsHelper(numbers, k, 0, 0, currentCombination, result);

        return result;
    }

    static void GenerateCombinationsHelper(int[] numbers, int k, int start, int currentSize, List<int> currentCombination, List<List<int>> result)
    {
        if (currentSize == k)
        {
            result.Add(new List<int>(currentCombination));
            return;
        }

        for (int i = start; i < numbers.Length; i++)
        {
            currentCombination.Add(numbers[i]);
            GenerateCombinationsHelper(numbers, k, i + 1, currentSize + 1, currentCombination, result);
            currentCombination.RemoveAt(currentCombination.Count - 1);
        }
    }
}

说明:
通过指定 k 的值来输出相应的组合,比如,k=2,即输出数组中两个元素的所有组合

进阶二:排列出集合的组合,所进行运算

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
		// 创建集合
        List<Item> itemsList = new List<Item>
		{
			new Item { Number = 1, Amount = 100 },
			new Item { Number = 2, Amount = 200 },
			new Item { Number = 3, Amount = 300 }
		};
		
		// 进行组合
		List<List<Item>> combinations = GenerateCombinations(itemsList);

		// 对组合结果进行运算
		StringBuilder sb = new StringBuilder(1024);
		foreach (var combination in combinations)
		{
			for (var i = 0; i < combination.Count; i++)
			{
				var item = combination[i];
				sb.Append(item.Number);
				if (i < combination.Count - 1)
				{
					sb.Append(" + ");
				}
			}
			var cash = combination.Sum(x => x.Amount);
			sb.AppendLine($" = {cash}");
		}
		
		// 打印结果
		Console.WriteLine(sb.ToString());
    }

    static List<List<Item>> GenerateCombinations(List<Item> numbers)
	{
		List<List<Item>> result = new List<List<Item>>();

		// 从 2 个元素开始进行组合
		for (int i=2; i <= numbers.Count; i++)
		{
			GenerateCombinationsHelper(numbers, i, 0, new List<Item>(), result);
		}

		return result;
	}

    static GenerateCombinationsHelper(List<Item> numbers, int k, int start, List<Item> currentCombination, List<List<Item>> result)
	{
		if (k == 0)
		{
			result.Add(new List<Item>(currentCombination));
			return;
		}

		for (int i = start; i < numbers.Count; i++)
		{
			currentCombination.Add(numbers[i]);
			GenerateCombinationsHelper(numbers, k - 1, i + 1, currentCombination, result);
			currentCombination.RemoveAt(currentCombination.Count - 1);
		}
	}
}

// 定义集合元素类
class Item
{
	// 编号
    public int Number { get; set; }
	
	// 金额
    public decimal Amount { get; set; }
}

总结

组合运算是面试中经常被问到的一个算法题,在实际业务中也会经常使用,希望以上例子对你有所帮助。

我是老杨,一个奋斗在一线的资深研发老鸟,让我们一起聊聊技术,聊聊人生。

都看到这了,求个点赞、关注、在看三连呗,感谢支持。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值