每日练习之排序——链表的合并;完全背包—— 兑换零钱

简介: 每日练习之排序——链表的合并;完全背包—— 兑换零钱

链表的合并

题目描述

运行代码

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{  int a[31];
    for(int i = 1;i <= 30;i++)
        cin>>a[i];
    sort(a + 1,a + 1 + 30);
    for(int i = 1;i < 30;i++)
       cout<<a[i]<<" ";
   cout<<a[30]<<endl;
    return 0;
}

代码思路

  1. 定义数组:定义了一个大小为31的整数数组a,但实际上我们只使用前30个位置(从a[1]a[30])。在C++中,数组通常从索引0开始,但这里为了某种原因(可能是题目要求或其他原因),代码从索引1开始。
  2. 输入数据:使用for循环从标准输入读取30个整数,并将它们存储在数组a的索引1到30中。
  3. 排序数据:使用std::sort函数对数组进行排序。注意,这里传递给sort函数的是数组的起始地址和结束地址(不包括结束地址对应的元素)。
  4. 输出数据:使用for循环输出排序后的数组元素。但是,这里有一个小错误:循环的条件是i < 30,这意味着它会输出索引从1到29的元素,而遗漏了索引为30的元素。
  5. 输出最后一个元素:在for循环之后,单独输出索引为30的元素。

改进代码

  1. 数组索引:为了与C++的常规做法保持一致,并避免潜在的错误,最好从索引0开始使用数组。这样,你就不需要为数组分配额外的空间,也不需要记住从哪个索引开始读取或写入数据。
  2. 输出循环:为了简洁起见,可以将输出索引为30的元素的代码移到for循环中。这样,你就不需要单独处理最后一个元素了。
#include<iostream>  
#include<algorithm>  
using namespace std;   
int main()  
{  
    int a[30]; // 直接定义大小为30的数组  
    for(int i = 0; i < 30; i++) // 从索引0开始读取数据  
        cin >> a[i];  
    sort(a, a + 30); // 直接使用数组的起始和结束地址  
    for(int i = 0; i < 30; i++) // 从索引0开始输出数据  
        cout << a[i] << " ";  
    cout << endl; // 在循环后直接输出换行符  
    return 0;  
}

兑换零钱

题目描述

运行代码

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int mod=1e9+7;
int a[20]={1,2,5,10,20,50,100,200,500,1000,2000,5000,10000},dp[100010];
int main()
{
  dp[0]=1;
  for(int i=0;i<13;i++)
        for(int j=a[i];j<=100000;j++)
            dp[j]=(dp[j]+dp[j-a[i]])%mod;
  int N,T;
  cin>>T;
  while( T-- )
  {
    cin>>N;
    cout<<dp[N]<<endl;
  }
   return 0;
}

代码思路

  1. 初始化dp[0]为1,因为凑成面额0只有一种方式(即不使用任何硬币)。
  2. 使用两个嵌套的循环来计算dp数组的其他元素。外层循环遍历硬币数组a,内层循环遍历从当前硬币面额到100000的所有可能面额。对于每个面额j,我们都检查是否可以使用当前硬币a[i]来凑成它。如果可以(即j >= a[i]),则dp[j]的值是原来的值加上dp[j-a[i]](即不使用当前硬币和使用当前硬币的凑法数之和)。
  3. 最后,程序读取测试用例数量T,然后对每个测试用例读取一个整数N,并输出dp[N],即凑成面额N的方法数。

改进建议

  1. 避免使用<bits/stdc++.h>:这个头文件虽然包含了几乎所有标准库,但它不是标准C++的一部分,而且会增加编译时间。建议只包含你需要的头文件。
  2. 数组大小:虽然这里定义dp数组的大小为100010是足够的,但如果你想要一个更通用的解决方案,你可以根据输入的最大可能值来动态分配这个数组的大小。
  3. 输入验证:虽然在这个问题中可能不需要,但在实际应用中,验证输入的有效性(例如,确保N是非负的)是一个好习惯。
  4. 注释:添加注释来解释代码的每个部分是如何工作的,以及为什么选择这种特定的实现方式,可以帮助其他人(或未来的你)更容易地理解代码。
  5. 优化:虽然对于这个问题来说,当前的实现已经足够快,但如果你在处理更大的面额或更多的硬币时,你可能需要考虑更高效的算法,如使用背包问题的优化技术。

改进代码

#include <iostream>  
#include <vector>  
using namespace std;  
const int MOD = 1e9 + 7;  
const int MAX = 100000; 
vector<int> coin = {1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000};  
// 动态规划表,用于存储凑成不同面额的方法数  
vector<int> Amount(MAX + 1, 0);  
int main() {  
    // 初始化凑成面额0的方法数为1  
   Amount[0] = 1;   
    // 动态规划计算凑成不同面额的方法数  
    for (int i = 0; i < coin.size(); i++) {  
        for (int j = coin[i]; j <= MAX; j++) {  
            Amount[j] = (Amount[j] + Amount[j - coin[i]]) % MOD;  
        }  
    }  
    int T, N;  
    cin >> T; // 读取测试用例数量   
    while (T--) {  
        cin >> N; // 读取当前测试用例的面额  
        cout <<Amount[N] << endl; // 输出凑成面额N的方法数  
    }   
    return 0;  
}


目录
相关文章
|
1月前
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
46 0
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
30 0
|
3月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
3月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
44 0
|
5月前
|
存储
2.顺序表_链表(附练习)
2.顺序表_链表(附练习)
|
5月前
23.合并K个升序链表
23.合并K个升序链表
|
5月前
|
存储 SQL 算法
LeetCode 83题:删除排序链表中的重复元素【面试】
LeetCode 83题:删除排序链表中的重复元素【面试】
|
5月前
|
存储 SQL 算法
LeetCode 题目 82:删除排序链表中的重复元素 II
LeetCode 题目 82:删除排序链表中的重复元素 II
|
5月前
|
存储 算法 数据挖掘
Leetcode二十三题:合并K个升序链表【22/1000 python】
Leetcode二十三题:合并K个升序链表【22/1000 python】
|
6月前
|
索引
【力扣刷题】回文链表、环形链表、合并两个有序链表
【力扣刷题】回文链表、环形链表、合并两个有序链表
37 0