1. 程式人生 > 其它 >【Lintcode】1509. Lemonade Change(配數學證明)

【Lintcode】1509. Lemonade Change(配數學證明)

技術標籤:# 貪心、動態規劃與記憶化搜尋演算法javaleetcode

題目地址:

https://www.lintcode.com/problem/lemonade-change/description

有個檸檬水攤,每瓶水價格是 5 5 5元。有一列顧客來買水,每次他們會支付 5 , 10 5,10 5,10 20 20 20元。攤販一開始沒有錢,但每次必須給顧客正確找零。給定顧客手裡的錢的序列,問該序列是否可以實現正確找零。

用兩個變數存攤販手裡有多少 5 5 5 10 10 10元( 20 20 20元鈔票數量不用存,因為找零用不上)。如果顧客手裡是 5 5 5元,那直接計數加 1 1 1;如果顧客手裡是 10 10

10元,那此時攤販手裡必須有 5 5 5元找零,如果沒有則返回false,否則將 5 5 5的計數減 1 1 1,並將 10 10 10的計數加 1 1 1;如果顧客手裡是 20 20 20元,則先儘量找 10 + 5 10+5 10+5,如果找不了,則找 5 + 5 + 5 5+5+5 5+5+5,如果還找不了,則返回false。最後如果能安全遍歷完序列,則返回true。

演算法正確性證明:
這裡用到貪心的思想,在於顧客手裡 20 20 20元的時候,要優先找零 10 + 5 10+5 10+5而不是 5 + 5 + 5 5+5+5 5+5+5。首先,如果返回true,那一定存在合法找錢方案,這一點很顯然。如果存在合法找錢方案,找到第一次與貪心法不同的找錢的時刻,說明這種方案找的錢是 5 + 5 + 5 5+5+5

5+5+5而不是貪心法的 10 + 5 10+5 10+5,此時,我們將這裡的 5 + 5 5+5 5+5替換為 10 10 10,後面也是這樣替換,如果哪裡必須要用到 10 10 10了,那麼就用 5 + 5 5+5 5+5頂上去。這樣的方案顯然也合法,它就被調整成了貪心方案,而貪心演算法是返回true的,所以演算法正確。

程式碼如下:

import java.util.List;

public class Solution {
    /**
     * @param bills: the Bill
     * @return: Return true if and only if you can provide every customer with correct change.
     */
public boolean lemonadeChange(List<Integer> bills) { // Write your code here. int five = 0, ten = 0; for (int i = 0; i < bills.size(); i++) { int cur = bills.get(i); if (cur == 5) { five++; } else if (cur == 10) { five--; if (five < 0) { return false; } ten++; } else { if (five > 0 && ten > 0) { five--; ten--; } else if (five >= 3) { five -= 3; } else { return false; } } } return true; } }

時間複雜度 O ( n ) O(n) O(n) n n n為顧客數量,空間 O ( 1 ) O(1) O(1)