649. Dota2 參議院
阿新 • • 發佈:2020-12-12
技術標籤:leetcode
第一次嘗試 暴力
本來想統計字串裡面R和D的數目,發現想得太簡單了
“DDRRR”
雖然R多,但卻是D贏了,因為D先行ban了兩個R,還剩一個R ban了一個D,然後剩下那個D又把R給ban了,最後5個只剩下一個D所以是D贏
第二次嘗試 模擬
觀察上面的投票過程,只有當佇列中能夠投票的元素均相同的時候才能宣佈勝利,否則每個元素都會禁止離它最近的下一個敵對元素,那麼我們按照這個策略來模擬
- 使用r和d來統計當前分別能夠投票的元素個數,使用flag陣列標記flag[i]是否有投票權利
- 遍歷佇列,直到r或d為0,執行以下操作
- 從當前元素開始尋找最近的敵對元素,修改其flag[i]=false
- 返回不為0的元素
class Solution:
def predictPartyVictory(self, senate: str) -> str:
size = len(senate)
r,d = 0,0
for ch in senate:
if ch == 'R':
r+=1
else:
d+=1
flag = [True] * size
ind = 0
while r!=0 and d!=0:
if flag[ind]:
ch = senate[ind]
j = (ind+1)%size
while True:
if ch == 'R' and senate[j] == 'D' and flag[j] == True:
d-=1
break
if ch == 'D' and senate[ j] == 'R' and flag[j] == True:
r-=1
break
j = (j+1)%size
flag[j] = False
ind = (ind+1)%size
# print(flag)
if r!=0:
return 'Radiant'
else:
return 'Dire'
通過了,但是效率很低,主要是往後找元素這個過程花費時間太長了
改進
我們只遍歷一輪,用r和d來表示當前擁有投票權的元素
- 如果當前元素是R,並且d==0,那麼r+=1,反之同理
- 如果當前元素是R,但是d!=0,那麼不做任何操作,反之同理
- 遍歷一輪後檢查r和d的數量
但是我們每個元素在一輪決策中只能投票一次,所以上面的遍歷還要改進,我們現在用兩個佇列r和d來儲存可以投票的元素
- 如果當前元素是R,d佇列為空,那麼入隊r佇列,否則d隊列出隊一個元素,儲存到res字串中等待下一輪投票,反之同理
- 取出res字串中的元素,重複上述遍歷
- 如果res為空,那麼我們檢查佇列元素,返回相應答案
class Solution:
def predictPartyVictory(self, senate: str) -> str:
size = len(senate)
r,d = [],[]
res = senate
while res!='':
senate = res
res = ''
for ch in senate:
if ch=='R':
if len(d)==0:
r.append('R')
else:
res+=d.pop()
else:
if len(r)==0:
d.append('D')
else:
res+=r.pop()
if len(r)!=0:
return 'Radiant'
else:
return 'Dire'
這次效率高了很多