【每日算法Day 99】你們可能不知道只用20萬贏到578萬是什麼概念

你們可能不知道只用 20 萬贏到 578 萬是什麼概念。 我們一般只會用兩個字來形容這種人:賭怪! 我經常說一句話,當年陳刀仔他能用 20 塊贏到 3700 萬,我 LBW 用 20 萬贏到 500 萬不是問題。 埋伏他一手,這個牌不能搶,這個牌不用搶,他死定了。 反手給一個超級加倍,悶聲發大財。他也超級加倍?但是不用怕,他的牌贏不了我。 五六七八九十,兩個炸,很牛逼這個牌,如果把這個 K 換成 J ,我這個牌將絕殺,但是換不得。 單走一個六,SB,直接把 K 走了。 走他一張 2 頂他。阿姨快點,阿姨,阿姨你 K 都不要嗎?阿姨你快點啊!阿姨別磨磨蹭蹭的。 五六七八九十。打錯了,應該打 2 的。 給阿姨倒杯茶好吧,阿姨給你倒一杯卡布奇諾。 給阿姨倒一杯卡布奇諾!開始你的炸彈秀,炸他炸他。漂亮! 十七張牌你能秒我?你能秒殺我?!你今天能十七張牌把盧本偉秒了,我!當!場!就把這個電腦屏幕喫掉!!!

題目鏈接

LeetCode 846. 一手順子[1]

題目描述

愛麗絲有一手(hand)由整數數組給定的牌。

現在她想把牌重新排列成組,使得每個組的大小都是 W,且由 W 張連續的牌組成。

如果她可以完成分組就返回 true,否則返回 false

說明:

  • 1 <= hand.length <= 10000
  • 0 <= hand[i] <= 10^9
  • 1 <= W <= hand.length

示例1

        輸入:
hand = [1,2,3,6,2,3,4,7,8], W = 3
輸出:
true
解釋:
愛麗絲的手牌可以被重新排列爲 [1,2,3],[2,3,4],[6,7,8]。
      

示例2

        輸入:
hand = [1,2,3,4,5], W = 4
輸出:
false
解釋:
愛麗絲的手牌無法被重新排列成幾個大小爲 4 的組。
      

題解

巧用 map

這也是最直觀的一個方法,用 map 來保存每個數出現的次數。

然後從最小的數開始,以它作爲順子的開頭,然後看順子裏的數在不在 map 裏,在就次數減一,不在就直接返回 false

接着重複上面步驟,最後直到 map 爲空,最後返回 true

map 的特性就是你取它的第一個鍵值對,它的 key 就是最小的,這就很方便了。

排序統計

首先對手牌從小到大進行排序,然後從最小的開始,作爲順子開頭,遍歷之後的數。如果在數組裏,並且沒有被訪問過,那麼就標記爲訪問過了。

注意可以提前終止遍歷,也就是如果發現某一個順子還沒遍歷完,但是訪問到的元素已經超過接在順子後的數了,那就直接返回 false

排序統計2

這題還有個解法,來自於題解區網友 zhanzq,感覺挺不錯的。但是我沒怎麼看懂,如果誰看懂了請教教我。

網友題解[2]

v2-a902d1a1574273c8e67a703b8619abaa_b.jpg

代碼

巧用 map(c++)

        class Solution {
public:
    bool isNStraightHand(vector<int>& hand, int W) {
        int n = hand.size();
        if (n%W) return false;
        map<int, int> count;
        for (auto x : hand) count[x]++;
        while (count.size()) {
            int start = count.begin()->first;
            for (int i = start; i < start+W; ++i) {
                if (count.find(i) == count.end()) return false;
                if (!--count[i]) count.erase(i);
            }
        }
        return true;
    }
};

      

排序統計(c++)

        class Solution {
public:
    bool isNStraightHand(vector<int>& hand, int W) {
        int n = hand.size();
        if (n%W) return false;
        if (W==1) return true;
        sort(hand.begin(), hand.end());
        vector<int> vis(n, 0);
        for (int i = 0; i < n; ++i) {
            if (vis[i]) continue;
            int cnt = 1;
            vis[i] = 1;
            for (int j = i+1; j < n; ++j) {
                if (hand[j]>hand[i]+cnt) break;
                if (!vis[j] && hand[j]==hand[i]+cnt) {
                    vis[j] = 1;
                    cnt++;
                    if (cnt == W) break;
                }
            }
            if (cnt != W) return false;
        }
        return true;
    }
};

      

排序統計2,來自於網友zhanzq(c++)

        class Solution {
public:
    bool valid(vector<int> &lst, int W){
        lst.push_back(0);
        int sz = lst.size();
        int pre = 0;
        vector<int> deltas(sz, 0);
        for(int i = 0; i < sz; i++){
            pre += deltas[i];
            if(pre < lst[i]){
                int delta = lst[i] - pre;
                pre = lst[i];
                if(i + W < sz){
                    deltas[i+W] -= delta;
                }
            }else if(pre > lst[i]){
                return false;
            }
        }
        return true;
    }

    bool isNStraightHand(vector<int>& hand, int W) {
        int sz = hand.size();
        if(sz%W){
            return false;
        }else{
            sort(hand.begin(), hand.end());
            vector<int> lst;
            int i = 0, j = 0;
            while(i < sz){
                while(j < sz && hand[i] == hand[j]){
                    j++;
                }
                lst.push_back(j - i);
                if(j >= sz){
                    break;
                }else if(hand[j] != hand[j-1] + 1){
                    lst.push_back(0);
                }
                i = j;
            }
            return valid(lst, W);
        }
    }
};

      

參考資料

[1]

LeetCode 846. 一手順子: leetcode-cn.com/problem

[2]

網友題解: leetcode-cn.com/problem

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章