文巾解题 679. 24 点游戏
1 題目描述
2 解題思路
2.1 遍歷所有可能情況
我們先找出四張牌所有可能的排列組合。
然后對(duì)于每一種排列組合,我們先提出排列組合中最前面的兩個(gè)數(shù)。然后對(duì)這兩個(gè)數(shù)進(jìn)行加\減\乘\除操作。將結(jié)果放入我們當(dāng)前考慮的排列組合中。
此時(shí)排列組合中有三個(gè)元素:原來(lái)的后兩個(gè)元素。和前兩個(gè)元素進(jìn)行數(shù)學(xué)計(jì)算后的結(jié)果。
慢的操作是對(duì)這三個(gè)數(shù)組成的序列,再求它們 的排列組合。但實(shí)際上后兩個(gè)數(shù)的順序我們是可以固定的。也就是說(shuō),如果我們接下來(lái)提取出來(lái)的兩個(gè)數(shù)。有前兩個(gè)數(shù)運(yùn)算后的結(jié)果,那么這個(gè)結(jié)果可能在運(yùn)算符的左邊,也可能在運(yùn)算符的右邊。這兩種情況我們都需要考慮
然后三個(gè)數(shù)組成的序列,經(jīng)過(guò)上面一部變成了兩個(gè)數(shù)。同第三步的考慮一樣。兩個(gè)操作數(shù)哪個(gè)在運(yùn)算符的左邊,哪個(gè)在右邊。我們都需要進(jìn)行討論和考慮。
還有一個(gè)tips。因?yàn)檫@種方法我們沒(méi)有排除掉除以0 的情況。為了防止除0報(bào)錯(cuò),進(jìn)行除法的時(shí)候,我們需要對(duì)被除數(shù)加上一個(gè)很小的數(shù)值。
class Solution:def judgePoint24(self, cards: List[int]) -> bool:ret=[]for i in cards:tmp=copy.deepcopy(cards)tmp.remove(i)for j in tmp:tmp1=copy.deepcopy(tmp)tmp1.remove(j)for k in tmp1:tmp2=copy.deepcopy(tmp1)tmp2.remove(k)l=tmp2[0]ret.append([i,j,k,l]) #四張牌所有的排列組合 ''' 求排列組合的大致思想是: 我們先從四個(gè)元素組成的序列中提取一個(gè); 然后從不含這個(gè)元素的三元素序列中提取一個(gè); 然后是兩個(gè)中選一個(gè),最后就是另外的一個(gè) '''def judge2(ab,cd):#print(ab,cd)return((abs(ab+cd-24)<0.001)or(abs(ab*cd-24)<0.001)or(abs(ab-cd-24)<0.001)or(abs(ab/(cd+0.0000001)-24)<0.001)or(abs(cd-ab-24)<0.001)or(abs(cd/(ab+0.0000001)-24)<0.001)) #三元序列中提取兩個(gè)進(jìn)行計(jì)算,得到的結(jié)果和序列中剩余的一個(gè),這兩個(gè)數(shù)能否通過(guò)某種運(yùn)算達(dá)到24def judge3(ab,c,d):#print(ab,c,d)return( judge2(ab+c,d) or judge2(ab-c,d)orjudge2(ab*c,d)orjudge2(ab/(c+0.0000001),d)orjudge2(c/(ab+0.0000001),d)orjudge2(c-ab,d)orjudge2(ab,c+d)orjudge2(ab,c-d)orjudge2(ab,c*d)orjudge2(ab,c/(d+0.0000001))) #四元序列中提取兩個(gè)進(jìn)行運(yùn)算,得到的結(jié)果和序列中剩余的兩個(gè),這三個(gè)數(shù)能否通過(guò)什么方法使結(jié)果到24def judge4(a,b,c,d):return( judge3(a+b,c,d) or judge3(a-b,c,d)orjudge3(a*b,c,d)orjudge3(a/(b+0.0000001),c,d)) #四個(gè)數(shù)能否通過(guò)某些操作使得結(jié)果為24for i in ret:if(judge4(i[0],i[1],i[2],i[3])==True):return(True)return(False)2.2 方法2 :遞歸
class Solution:def judgePoint24(self, nums: List[int]) -> bool:TARGET = 24EPSILON = 1e-6ADD, MULTIPLY, SUBTRACT, DIVIDE = 0, 1, 2, 3def solve(nums: List[float]) -> bool:if len(nums) == 1:return abs(nums[0] - TARGET) < EPSILON #只剩下一個(gè)數(shù)了,就判斷這個(gè)數(shù)和24之間的差距是否在臨界差距以內(nèi) #在的話,那么說(shuō)明可以通過(guò)運(yùn)算得到24for i, x in enumerate(nums):for j, y in enumerate(nums):if i != j: #從nums中找不同的兩個(gè)數(shù)(區(qū)別于方法2.1的思路)newNums = list()for s, z in enumerate(nums):if s != i and s != j:newNums.append(z) #找第三個(gè)數(shù)for k in range(4):if k < 2 and i > j:continue ''' 加和乘運(yùn)算,而且第一個(gè)運(yùn)算數(shù)比第二個(gè)大 這說(shuō)明之前在x等于第二個(gè)運(yùn)算數(shù)的時(shí)候,x+y 或者x*y已經(jīng)計(jì)算過(guò)了 所以不用再次計(jì)算,直接繼續(xù)循環(huán) '''if k == ADD:newNums.append(x + y)elif k == MULTIPLY:newNums.append(x * y)elif k == SUBTRACT:newNums.append(x - y)elif k == DIVIDE:if abs(y) < EPSILON:continuenewNums.append(x / y)if solve(newNums):return True #如果x,y運(yùn)算的結(jié)果和nums中剩下的兩個(gè)數(shù)組成的三個(gè)數(shù)可以算出24,那么返回TruenewNums.pop() ''' 不然的話,在三元素序列中,把當(dāng)前算的這個(gè)達(dá)不到24的x,y運(yùn)算結(jié)果pop出來(lái), 然后看下一個(gè)操作符算出來(lái)的X,Y結(jié)果,和nums中剩下的兩個(gè)元素組成的三元素序列滿足不滿足條件要求 '''return Falsereturn solve(nums)2.3 方法3:dfs
class Solution:def judgePoint24(self, cards: List[int]) -> bool:def dfs(nums):if len(nums) == 1:return abs(nums[0] - 24) < 0.00001 #序列中只有最后一個(gè)數(shù)了,進(jìn)行判斷for i in range(len(nums)-1):for j in range(i+1, len(nums)):x, y = nums[i], nums[j] #提取兩個(gè)不一樣的數(shù)(這里假設(shè)x在序列中的排位一定在y前面) #所以之后考慮減法和除法的時(shí)候,需要分別考慮x和y在除/減數(shù)和被除/減數(shù)的情況rst = nums[:i] + nums[i+1:j] + nums[j+1:] #x和y元素以外的元素拼成一個(gè)序列a = dfs(rst + [x + y])b = dfs(rst + [x - y])c = dfs(rst + [y - x])d = dfs(rst + [x * y])e = (y != 0) and dfs(rst + [x / y])f = (x != 0) and dfs(rst + [y / x]) #將x,y經(jīng)過(guò)不同操作數(shù)的結(jié)果放到rst中,拼接而成的序列繼續(xù)進(jìn)行dfsif a or b or c or d or e or f:return Truereturn Falsereturn dfs(cards)總結(jié)
以上是生活随笔為你收集整理的文巾解题 679. 24 点游戏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: GNN 笔记:图上的傅里叶变换
- 下一篇: 博弈论笔记:逆向选择与非对称信息