1. 程式人生 > 其它 >LeetCode-846.一手順子

LeetCode-846.一手順子

 LeetCode-846.一手順子

  題目連結(微信開啟):https://mp.weixin.qq.com/s/RWzrpg1Q4Dke7UNR4T34PA

一、題目描述

  Alice有一手牌:整數陣列hand,需要將它分組,問是否可以將其分成每組牌數都是groupSize張,且每組牌數的數字需要連續。可以的話輸出:true,否則:false。

示例 1:

輸入:hand = [1,2,3,6,2,3,4,7,8], groupSize = 3
輸出:true
解釋:Alice 手中的牌可以被重新排列為 [1,2,3],[2,3,4],[6,7,8]。

示例 2:

輸入:hand = [1
,2,3,4,5], groupSize = 4 輸出:false 解釋:Alice 手中的牌無法被重新排列成幾個大小為 4 的組。

注意:

  • 1 <= hand.length <= 104

  • 0 <= hand[i] <= 109

  • 1 <= groupSize <= hand.length

 

二、題目分析

  我先說說自己能想到的和不能想到的一些問題吧,

(I)能想到的

這個hand陣列能不能分成每組為:groupSize個數,首要條件需要滿足:

1、hand的個數能被groupSize 除盡,即:

hand.length mod groupSize == 0

2、需要對整個hand陣列,進行從小到大的排序

3、要統計每個數字的出現次數

  用另一個數組cnt,cnt[hand[i]] 表示hand[i] 這個數的出現次數。比如,未對陣列hand排序前,hand[2],hand[7],hand[11],hand[18]都是數字3,那麼cnt[3]=4。

4、當某個hand[i]能分成一對順子後,這個hand[i]要被剔除,然後出現次數要遞減1。

  拿上面的示例2來說,沒成順子前應得到次數陣列:

cnt[1]= 1
cnt[2]= 2
cnt[3]= 2
cnt[4]= 1
cnt[6]= 1
cnt[7]= 1
cnt[8]= 1

 當把1,2,3成一對順子後,次數陣列變成:

cnt[1]= 0    #成順子,次數減去1
cnt[2]= 1    #成順子,次數減去1
cnt[3]= 1    #成順子,次數減去1
cnt[4]= 1
cnt[6]= 1
cnt[7]= 1
cnt[8]= 1

5、最後就是成順子的一些組合,數字有重疊的是情況1~3,數字不重疊的是情況4

(II)不能想到的

  上面都是些零碎的分析,不知道怎麼轉化為程式碼。

  主要體現在:

(1)當從hand陣列拿走一對groupSize牌數後,次數陣列遞減1,之後如何保證hand陣列,最終剩下的數能不能剛好都成順子;

(2)另外一個問題是,這個位置移動怎麼去走,例如上面圖的情況1,需要分成每組groupSize=2的順子,當從中拿走1、2成順子後,下一個順子位置是從3,4,還是從1,2去拿。然後就被自己搞混了。

 

三、最終解析

  後來我看了題解,發現沒想象中複雜!以下摘自題解:

假設尚未分組的牌中,最小的數字是 x,則如果存在符合要求的分組方式,x 一定是某個組中的最小數字(否則 x 不屬於任何一個組,不符合每張牌都必須被分到某個組),該組的數字範圍是 [x,x+groupSize−1]。在將 x 到 x+groupSize−1 的 groupSize 張牌分成一個組之後,繼續使用貪心的策略對剩下的牌分組,直到所有的牌分組結束或者無法完成分組。如果在分組過程中發現從最小數字開始的連續 groupSize 個數字中有不存在的數字,則無法完成分組

  對我第一個疑問,首先hand陣列能被groupSize除得盡,如果都能成順子配對的話,是不會存在多餘的數成不了順子的

  第二個疑問:怎麼移動下一對順子的位置。排完序順著來,直到次數陣列遞減到0,我們再移動位置就好了。剛不是提到情況1,如果1、2成順子,下一個順子位置應從1、2去配對,而不是直接走到3,4。 因為cnt[1]和cnt[2]還沒成0。

  用虛擬碼控制這個移動的位置,這個晚點我再補充。。。。