1. 程式人生 > >程式設計師面試題精選100題(40)-撲克牌的順子[演算法]

程式設計師面試題精選100題(40)-撲克牌的順子[演算法]

題目:從撲克牌中隨機抽5張牌,判斷是不是一個順子,即這5張牌是不是連續的。2-10為數字本身,A1J11Q12K13,而大小王可以看成任意數字。

分析:這題目很有意思,是一個典型的寓教於樂的題目。

我們需要把撲克牌的背景抽象成計算機語言。不難想象,我們可以把5張牌看成由5個數字組成的陣列。大小王是特殊的數字,我們不妨把它們都當成0,這樣和其他撲克牌代表的數字就不重複了。

接下來我們來分析怎樣判斷5個數字是不是連續的。最直觀的是,我們把陣列排序。但值得注意的是,由於0可以當成任意數字,我們可以用0去補滿陣列中的空缺。也就是排序之後的陣列不是連續的,即相鄰的兩個數字相隔若干個數字,但如果我們有足夠的0

可以補滿這兩個數字的空缺,這個陣列實際上還是連續的。舉個例子,陣列排序之後為{01345}。在13之間空缺了一個2,剛好我們有一個0,也就是我們可以它當成2去填補這個空缺。

於是我們需要做三件事情:把陣列排序,統計陣列中0的個數,統計排序之後的陣列相鄰數字之間的空缺總數。如果空缺的總數小於或者等於0的個數,那麼這個陣列就是連續的;反之則不連續。最後,我們還需要注意的是,如果陣列中的非0數字重複出現,則該陣列不是連續的。換成撲克牌的描述方式,就是如果一副牌裡含有對子,則不可能是順子。

基於這個思路,我們可以寫出如下的程式碼:

// Determine whether numbers in an array are continuous
// Parameters: numbers: an array, each number in the array is between
//             0 and maxNumber. 0 can be treeted as any number between
//             1 and maxNumber
//             maxNumber: the maximum number in the array numbers
bool IsContinuous(std::vector<int> numbers, int maxNumber)
{
    if(numbers.size() == 0 || maxNumber <=0)
        return false;
 
    // Sort the array numbers.
    std::sort(numbers.begin(), numbers.end());
 
    int numberOfZero = 0;
    int numberOfGap = 0;
 
    // how many 0s in the array?
    std::vector<int>::iterator smallerNumber = numbers.begin();
    while(smallerNumber != numbers.end() && *smallerNumber == 0)
    {
        numberOfZero++;
        ++smallerNumber;
    }
 
    // get the total gaps between all adjacent two numbers
    std::vector<int>::iterator biggerNumber = smallerNumber + 1;
    while(biggerNumber < numbers.end())
    {
        // if any non-zero number appears more than once in the array,
        // the array can't be continuous
        if(*biggerNumber == *smallerNumber)
            return false;
 
        numberOfGap += *biggerNumber - *smallerNumber - 1;
        smallerNumber = biggerNumber;
        ++biggerNumber;
    }
 
    return (numberOfGap > numberOfZero) ? false : true;
}


本文為了讓程式碼顯得比較簡潔,上述程式碼用C++的標準模板庫中的vector來表達陣列,同時用函式sort排序。當然我們可以自己寫排序演算法。為了有更好的通用性,上述程式碼沒有限定陣列的長度和允許出現的最大數字。要解答原題,我們只需要確保傳入的陣列的長度是5,並且maxNumber13即可。

本文已經收錄到《劍指Offer——名企面試官精講典型程式設計題》一書中,有改動,書中的分析講解更加詳細。歡迎關注。