題目以下java
零和博弈問題:表示全部博弈方的利益之和爲零或者是一個常數,即一方有得其餘方必有失,且在博弈中各方是不會合做的。解決此類問題的方法有極小化極大算法等,那就先來學習一下這個極小化極大算法:Minimax算法,是一種找出失敗的最大可能性中的最小值的算法。node
算法僞代碼(維基百科)算法
function minimax(node, depth) if node is a terminal node or depth = 0 return the heuristic value of node if the adversary is to play at node let α := +∞ foreach child of node α := min(α, minimax(child, depth-1)) else {we are to play at node} let α := -∞ foreach child of node α := max(α, minimax(child, depth-1)) return α
從僞代碼中能夠看到:在對手回合時,算法默認對手的收益爲無窮大;在本身回合時收益爲無窮小。在迭代過程當中,須要進行玩家判斷,由於遊戲的目的就是最小化對手的優點而最大化本身的利益,因此在對手的回合時,對手須要讓我最小化利益min,而在本身的回合時,我確定是最大化本身的利益,因此用max。那麼Max和Min分別都是怎麼計算出利益大小的呢?遞歸!不知道利益大小就遞歸地往下問,問到最後再遞歸地回答上來,利益就計算出來了數組
那針對這道題的解答思路就有了:ide
咱們用一個solve(nums)函數來計算當前玩家從nums中能夠得到的最大收益,當收益>=0時,玩家1獲勝。函數
solve(nums) = max(nums[0] - solve(nums[1:]), nums[-1] - solve(nums[:-1]))學習
爲何是nums[0]-solve(nums[1:])而不是+呢?由於玩家拿完一個數以後就輪到別人了,此時solve函數是別人的收益,咱們用累計本身收益,並扣除對手收益的方式來表示本身的收益最後是否比對手多,若是結果大於0就表示比對手多。spa
(備註:nums[-1],nums[:-1]的意思:Python的索引方式,帶冒號的叫作數組的「切片」,冒號前的數是起點的索引,後面的是終點索引。若是沒有起點默認是0,若是沒有終點默認就是到最後。舉個栗子: nums[1,2,3,4,5],則 nums[-1] = 5 , nums[ :-1] = [1,2,3,4] , nums[ 1:] = [2,3,4,5] )code
Java實現遞歸
public class PredictTheWinnerBter { public static boolean solution(int[] nums){ return helper(nums,0,nums.length - 1) >= 0; } private static int helper(int[] nums,int s,int e) { return s == e ? nums[e] : Math.max(nums[s] - helper(nums,s+1,e), nums[e] - helper(nums,s,e-1)); } public static void main(String[] args){ int[] nums = new int[]{1,5,255,2}; System.out.println(solution(nums)); } }
這道題剛開始真的不會寫,但這種題目能夠說是很是經典了。還有解法是自上而下的DP(動態規劃),找時間研究一下。
參考:Leetcode解題報告