当前位置: 首页 > ai >正文

贪心算法解决钱币找零问题(二)

问题描述

钱币找零问题是算法领域的经典问题,具体描述为:给定一定金额和一组不同面额的钱币,如何使用最少数量的钱币组合出该金额?本文将使用贪心算法解决这一问题,并通过代码实现展示其具体应用。

例如:

  • 输入:面额 [25, 10, 5, 1],金额 41
  • 输出:总张数 4,各面额使用数量 1 1 1 1(即 25+10+5+1=41)

贪心算法的适用场景

贪心算法通过 "每次选择局部最优解" 来寻求全局最优解,适用于具有 "贪心选择性质" 的问题。对于钱币找零问题:

  • 当钱币系统满足 "较大面额是较小面额的倍数" 时(如人民币、美元等十进制货币),贪心算法可得到最优解
  • 典型反例:面额 [1, 3, 4] 找零 6,贪心会选择 4+1+1(3 张),但最优解是 3+3(2 张)

本文实现基于满足贪心选择性质的钱币系统。

代码实现与解析

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;/*** 钱币找零函数(贪心算法)* @param amount 需要找零的金额* @param denominations 钱币面额数组* 输出格式:总张数 每种面额的使用数量(按面额从大到小排序)*/
void coinChange(int amount, vector<int>& denominations) {// 核心步骤1:将面额从大到小排序,确保优先使用大面额sort(denominations.begin(), denominations.end(), [](const int a, const int b) {return a > b;});int n = denominations.size();vector<int> count(n, 0);  // 记录每种面额的使用数量int totalCoins = 0;       // 总钱币数量// 核心步骤2:贪心选择——优先使用当前最大面额for (int i = 0; i < n; i++) {// 只有当剩余金额大于等于当前面额时才使用if (amount >= denominations[i]) {count[i] = amount / denominations[i];  // 计算最多能使用的张数totalCoins += count[i];                // 累加总张数amount -= count[i] * denominations[i]; // 减去已找零的金额}// 提前退出:金额已找完,无需继续循环if (amount == 0) {break;}}// 处理无法完全找零的情况if (amount > 0) {cout << "无法用给定面额完全找零,剩余金额:" << amount << endl;return;}// 输出结果cout << totalCoins << " ";for (int j = 0; j < n; j++) {if (j > 0) cout << " ";cout << count[j];}cout << endl;
}int main() {int typeCount;     // 面额种类数量int targetAmount;  // 目标找零金额cout << "请输入面额种类和目标金额(空格分隔):";cin >> typeCount >> targetAmount;// 处理金额为0的特殊情况if (targetAmount == 0) {cout << "0";for (int i = 0; i < typeCount; i++) {cout << " 0";}cout << endl;return 0;}vector<int> denominations(typeCount);cout << "请输入" << typeCount << "种面额(空格分隔):";for (int i = 0; i < typeCount; i++) {cin >> denominations[i];// 验证面额有效性if (denominations[i] <= 0) {cout << "错误:面额必须为正整数" << endl;return 1;}}coinChange(targetAmount, denominations);return 0;
}

核心逻辑解析

  1. 排序面额

    sort(denominations.begin(), denominations.end(), greater<int>());
    

    这是贪心算法的关键,通过从大到小排序,确保每次都优先使用最大面额,从而最小化总张数。

  2. 贪心选择过程

    if (amount >= denominations[i]) {count[i] = amount / denominations[i];totalCoins += count[i];amount -= count[i] * denominations[i];
    }
    

    对每种面额,计算最多能使用的张数(金额 / 面额),更新剩余金额和总张数。注意判断条件使用>=而非>,否则会漏掉 "金额恰好等于面额" 的情况。

  3. 提前终止与异常处理

    • amount == 0时提前退出循环,减少无效计算
    • 若循环结束后仍有剩余金额,说明无法完全找零

测试案例与运行结果

案例 1:正常找零

输入:
4 41
25 1 10 5处理过程:
1. 排序后面额:25, 10, 5, 1
2. 25元:1张(41-25=16)
3. 10元:1张(16-10=6)
4. 5元:1张(6-5=1)
5. 1元:1张(1-1=0)输出:
4 1 1 1 1

案例 2:无法完全找零

输入:
210
3 5输出:
无法用给定面额完全找零,剩余金额:1

案例 3:金额为 0

输入:
3 0
1 2 5输出:
0 0 0 0

代码优化点说明

  1. 命名规范:使用denominations(面额)、totalCoins(总张数)等语义化变量名,提高可读性。

  2. 鲁棒性处理

    • 验证输入面额为正数
    • 处理金额为 0 的边界情况
    • 检测无法找零的场景
  3. 效率优化

    • 排序后提前终止循环
    • 使用引用传递避免向量拷贝

贪心算法的局限性

虽然贪心算法实现简单、效率高(时间复杂度 O (n log n),主要消耗在排序),但存在明显局限性:

  • 仅适用于特定钱币系统(如面额为 {1,5,10,20,50})
  • 无法保证在任意面额组合下得到最优解

若需解决任意面额的最优找零问题,需采用动态规划算法,时间复杂度为 O (amount×n),空间复杂度为 O (amount)。

总结

本文实现的贪心算法是解决常规钱币系统找零问题的高效方案,核心思想是 "每次选择最大面额"。代码通过排序、贪心选择和边界处理,完整实现了找零功能并输出详细结果。实际应用中,需根据具体钱币系统选择合适的算法 —— 常规货币系统用贪心,特殊面额组合则需动态规划。

http://www.xdnf.cn/news/19472.html

相关文章:

  • 基于单片机倒车雷达/超声波测距设计
  • Linux->网络入门
  • 《论文阅读》从心到词:通过综合比喻语言和语义上下文信号产生同理心反应 2025 ACL findings
  • infinityfree mysql 加入数据库部分 filezilla 设备共享图片和文本不用浏览器缓存
  • 第六章 Vue3 + Three.js 实现高质量全景图查看器:从基础到优化
  • hive表不显示列注释column comment的问题解决
  • Linux signal 图文详解(二)信号发送
  • 为什么服务器接收 URL 参数时会接收到解码后的参数
  • DHT11-温湿度传感器
  • openEuler2403部署Redis8集群
  • 京东入局外卖,还有很多问题。
  • Ubuntu 服务器实战:Docker 部署 Nextcloud+ZeroTier,打造可远程访问的个人云
  • 学习 Android (十八) 学习 OpenCV (三)
  • OpenHarmony 分布式感知中枢深度拆解:MSDP 框架从 0 到 1 的实战指南
  • 餐饮外卖同城配送酒水寄存餐品加价换购促销小程序APP
  • Windows 安装配置解压版MongoDb
  • TFT屏幕:STM32硬件SPI+DMA+队列自动传输
  • 【RelayMQ】基于 Java 实现轻量级消息队列(五)
  • 2025 最新Vue前端面试题目 (9月最新)
  • AI 重构医疗诊断:影像识别准确率突破 98%,基层医院如何借技术缩小诊疗差距?
  • 设备服务管理上报方案
  • 两轮车车机 OS 演进路线深度解析
  • libmodbus源码分析
  • 【前端】《手把手带你入门前端》前端的一整套从开发到打包流程, 这篇文章都会教会你;什么是vue,Ajax,Nginx,前端三大件?
  • 差角函数差角矩阵位置编码
  • 无需服务器也能建网站:Docsify+cpolar让技术文档分享像写笔记一样简单
  • 手机版碰一碰发视频源码搭建,技术实现与实操指南
  • 鸿蒙开发进阶(HarmonyOS)
  • Unity中多线程与高并发下的单例模式
  • MobaXterm介绍