!!!题解 | 兑换零钱(一) 妙趣横生 尤其是对于凑不成的处理非常自然

兑换零钱(一)

https://www.nowcoder.com/practice/3911a20b3f8743058214ceaa099eeb45

#include <algorithm>
#include <climits>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 最少货币数
     * @param arr int整型vector the array
     * @param aim int整型 the target
     * @return int整型
     */
    int minMoney(vector<int>& arr, int aim) {
        // write code here
        int size=arr.size();
        if(size==0)return -1;
        if(aim==0)return 0;
        sort(arr.begin(), arr.end());
        int min1=arr[0];
        //int max=arr[size-1];
        if(min1>aim)return -1;
        //这个例子里自底向下最好理解。
        //从小面值开始 从小到大找到中间历经的所有金额的最少货币数目,直到增长到最大值为止。
        /******************************
		这里的关键在于,如果求金额大小为N的结果,因为不知道最后拿的一枚硬币是哪一枚,
        所以就穷举,假设拿的硬币是这些中的一个,然后再求它的子问题,也就是金额为N-Arr【j】最少的钱币是多少。
        这样其实可以自下向上
        */
        vector<int> res(aim+1,aim+1);//dp数组
        res[0]=0;
        for (int i=1; i<=aim; i++) {//i是和下标相对应 从1开始
            for(int j=0;j<size;j++){
                if(arr[j]<=i){
                    res[i]=min(res[i],res[i-arr[j]]+1);//会发生访问越界吗
                    //不会 因为进入条件分支要满足arr[j]<=i,所以最多访问到res[0]
                    //但这个初始化不好。dp数组设置为INTMAX会没有余量,+1就直接溢出了。
                    //可以设为aim+1;因为正常结果绝对不会超过aim。
                    /*这个min(res[i],res[i-arr[j]]+1);也很绝,因为他也覆盖了无法凑成的情况。
                    例如只有2 凑出5.下标1=aim+1;下标2=1;下标3虽然进入分支,但比较之后发现是和1的aim+2比,所以保持自身的aim+1.非常的自然
                    */
                }
			  else break;//这里break是因为当前面值已经大于金额了,所以后面的也肯定大于金额了,所以后面的就不用再匹配了,这样可以节省一些时间。当然也可以不排序,直接全部进行匹配
            }
        }
        return res[aim]==aim+1?-1:res[aim];
    }
};

全部评论

相关推荐

小牛炒肉:好大的官威居然不是什么官
点赞 评论 收藏
分享
03-31 14:46
已编辑
门头沟学院 Web前端
励志成为双港第一ja...:这其实很正常,离的太远了,他认为你不会来,就为了混个面试,而且成本很高,实习生都优先选本地高校。吃了地域的亏,所有很多时候地域可能比院校层次更重要。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务