[经典面试题]通过不同面值的硬币,求出组合出n有多少种组合情况

这篇博客介绍了如何使用迭代和递归方法解决使用特定面值硬币组合成目标金额的问题。文章提供了两种算法实现,一种是二维数组的迭代法,另一种是递归法。这两种方法都以1, 5, 10, 25作为硬币面值,用于计算组合出目标金额的方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过不同面值的硬币,求出组合出n有多少种组合情况

本题的一个具体情况如下

给定n,求出使用给定的1,5,10,25的硬币组合出n 的组合方式有多少种

第一种:迭代法

思路分析:
例如 15

  1. 不使用10面值
    a. 不使用5面值 res = 1;
    b. 使用1个5面值 res = 1
    c. 使用2个5面值 res = 1;
    d. 使用3个5面值的 res = 1;

  2. 使用一个10面值
    a. 不使用5面值 res = 1;
    b.使用一个5面值 res = 1;

sum = 6
由上述例子可以想到,n的组合方式由两个维度决定

  1. 可使用面值的个数
  2. 使用面值之后所剩的 n - x(x为使用次数)*面值

所以本题的迭代方法需要使用到二维数组

图解如下

在这里插入图片描述

/**
	 * 迭代写法,使用二维数组的形式模型结果描述
	 */
	public static int[][] countWays1(int n, int[] arr) {
		//规定数组大小 行:代表可用的面值  列代表 n
		int[][] res = new int[arr.length][n+1];
		//初始化 n为0时,res 1;  arr【1】 = 1时, res = 1;
		for (int i = 0; i < res[0].length; i++) {
			res[0][i] = 1;
		}
		for (int i = 0; i < res.length; i++) {
			res[i][0] = 1;
			res[i][1] = 1;
		}
		
		//填数组空缺的值
		for (int i = 1; i < res.length; i++) {
			for (int j = 2; j < res[0].length; j++) {
				//计数组合进行求和
				int sum = 0;
				//对最大的可用面值 进行计数 循环
				int times = j / arr[i]; 
				//通过对 可用最大面值的情况, 分类, 取上一层数组进行 计算 组合数
				for (int k = times; k >= 0; k--) {
					int surplus = j - arr[i]*k ;
					sum += res[i-1][surplus];
				}
				res[i][j] = sum;
			}
		}
		
		for (int i = 0; i <= n; i++) {
			System.out.print(i +" ");
			if (i == n) {
				System.out.println();
			}
		}
		for (int[] is : res) {
			
			for (int is2 : is) {
				System.out.print(is2+" ");
			}
			System.out.println();
		}
		return res;
	}

递归写法

	public static int countWay(int n) {
		if (n <= 0) {
			return 0;
		}
		
		return countWays(n, new int[]{1,5,10,25},  3);
	}
	
	/**
	 * 递归写法
	 * @param n   需要组合的数
	 * @param arr 给定的硬币数值	
	 * @param cur 能使用的最大面值硬币
	 * @return
	 */
	public static int countWays(int n, int[] arr, int cur ) {
		// TODO Auto-generated method stub
		if (cur == 0) {
			return 1;
		}
		//返回的结果
		int res = 0;
		//多分枝递归,通过规定能够使用最大面值的个数进行 递归
		//例如 15  1. 不使用10面值    a. 不使用5面值  res = 1; b. 使用1个5面值  res = 1  c. 使用2个5面值  res = 1; d. 使用3个5面值的  res = 1;
		//         2. 使用一个10面值   a. 不使用5面值  res = 1; b.使用一个5面值  res = 1;
		//  		 sum  = 6;
		for (int i  = 0; i * arr[cur] <= n; i++) {
			int surplus = n - i * arr[cur];
			res += countWays(surplus, arr, cur-1);
			
		}
		
		return res;
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值