C语言/860.(柠檬水找零)Lemonade Change

先上题目


在柠檬水摊上,每一杯柠檬水的售价为 5 美元。

顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

示例:




思路:题目很长,希望大家能耐心看完。题意类型是给定一个数组,判断能不能走到数组最后。首先我们至少需要遍历一次数组,在数组遍历的过程,对零钱“张数”进行计数,在通过张数来判断是否能完成找零。“5”不用找零直接收下,“10”手中至少有一张“5”,"20"手中至少有一张“10”和一张“5”或者至少3张“5”(这里需要考虑优先级,就像在日常生活中,我们找钱的过程会给面值大的钱。否则后面就没有“5”,就无法对“10”找零)


代码一:(耗时8ms     if-else if-else)

bool lemonadeChange(int* bills, int billsSize) {
    int fiveChange=0,tenChange=0,i=0;
        while(i<billsSize){
            if(bills[i]==5){
                fiveChange++;
            }else if(bills[i]==10){
                if(fiveChange>=1){
                    fiveChange--;
                    tenChange++;
                }else{
                    return false;
                }
            }else{
                if(fiveChange>=1&&tenChange>=1){
                    fiveChange--;
                    tenChange--;
                    
                }else if(fiveChange>=3){
                    fiveChange-=3;
                }else{
                    return false;
                }
            }
            i++;
        }

    return true;
}

代码二:(耗时4ms   switch case)

bool lemonadeChange(int* bills, int billsSize) {
    int fiveChange=0,tenChange=0,i=0;
        while(i<billsSize){
            switch(bills[i]){
                case 5:
                        fiveChange++;
                        break;
                case 10:
                        if(fiveChange>=1){
                            fiveChange--;
                            tenChange++;
                        }else{
                            return false;
                        }
                        break;
                case 20:
                        if(fiveChange>=1&&tenChange>=1){
                            fiveChange--;
                            tenChange--;
                            
                        }else if(fiveChange>=3){
                            fiveChange-=3;
                        }else{
                            return false;
                        }
                        break;
                default:
                        break;
            }
            
            i++;
        }

    return true;
}

给了两种做法:都是平时习惯的做法。在这里有个算法效率的注意点:

if 语句每一句都是独立的,例如:
if (i== 0) ...

else if (i == 1) ...

这样 i 要被读入寄存器两次,0 和 1 分别被读入寄存器一次。于是我们会发现其实 i 读两次是有点多余的,在全部比较完之前只需要一次读入寄存器就行了,其余都是额外开销。但是if 语句必须每次都把里面的两个数从内存拿出来读到寄存器,因为它不知道你其实比较的是同一个i。
于是 switch case 就出来了,把上面的改成 switch case 版本:
switch (i) {
        case 0:
                break;
        case 1:
}
因为当虚拟机读到switch的时候将所有的判断数据都加载在内存中了,而if是边判断边加载,所以就慢一些,
一般如果判断数据不多,而且是byte,short,int或是char类型的时候一般用switch,那样效率比较高.


扩展:假设我要最后要进行算账?那应该如何做?

        我们可以加上一个twentyChange进行计数,最后通过张数进行“+5”“+10”“+20”。面额增加同理

猜你喜欢

转载自blog.csdn.net/qq_38959715/article/details/80918681