国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

486. Predict the Winner

2019-11-11 02:30:49
字體:
來源:轉載
供稿:網友

Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array followed by the player 2 and then player 1 and so on. Each time a player picks a number, that number will not be available for the next player. This continues until all the scores have been chosen. The player with the maximum score wins.

Given an array of scores, PRedict whether player 1 is the winner. You can assume each player plays to maximize his score.

Example 1:

Input: [1, 5, 2]Output: FalseExplanation: Initially, player 1 can choose between 1 and 2. If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2). So, final score of player 1 is 1 + 2 = 3, and player 2 is 5. Hence, player 1 will never be the winner and you need to return False.

Example 2:

Input: [1, 5, 233, 7]Output: TrueExplanation: Player 1 first chooses 1. Then player 2 have to choose between 5 and 7. No matter which number player 2 choose, player 1 can choose 233.Finally, player 1 has more score (234) than player 2 (12), so you need to return True representing player1 can win.

Note:

1 <= length of the array <= 20.Any scores in the given array are non-negative integers and will not exceed 10,000,000.If the scores of both players are equal, then player 1 is still the winner.

【問題分析】

 1、該問題是兩個人交替從一個數組兩端獲取一個數字,每次每個人只能獲取一個,最終獲取的數字之和最大的獲勝,問第一個人能否獲勝

 2、該問題的解法有兩種: 

        一種是建立二叉樹方法:

        A、建立兩顆二叉樹,第一顆的根節點是第一個數字,第二顆的根節點是第二個數字

        B、建樹過程每次從當前剩余元素中取最左端和最右端的元素,分別作為當前節點的左孩子和右孩子,依次遞歸建立二叉樹

        C、兩棵樹從根節點到葉節點的路徑總個數為2^(n-1)個,遍歷所有路徑,依次計算路徑中1、3、5...個節點之和,

        D、如果大于所有節點只和的一半,或者大于2、4、6...節點數字只和,則第一個取數字者可以獲勝,否則無法獲勝

        另一種是動態規劃算法:

        A、問題定義是:從數組下標0到n-1之間取數字的規則是交替進行,第一個人從數組首或尾取一個,第二個人從剩余數組元素首或尾取一個,

               依次交替直到取完所有數字

        B、定義dp[i][j] 表示數組下標i到j之間取數字為子問題,它等于能夠在i到j之間獲得的所有數字之和和的最大值

               目標是第一個人能否在0到n-1之間的所有數字中取得數字只和大于數組所有元素之和的1/2,即dp[0][n-1]

        C、dp[i][j]表示第一個人能夠從i到j之間獲取的所有數字之和的最大值,那么

               dp[i+1][j]表示第二個人能夠在i-1到j之間獲取的所有數字之和的最大值,

               dp[i][j-1]表示第二個人能夠在i到j-1之間獲取的所有數字之和的最大值

        D、sum[i+1][j] - dp[i+1][j]表示第一個人取第i個元素以后,能夠在i+1到j之間獲取子數組之和的最大值

               sum[i][j-1] - dp[i][j-1]標識第一個人取第j個元素以后,能夠在i到j-1之間獲取子數組之和的最大值

               由于dp[i][j]表示每個人都試圖獲取當前下標i到j之間字數組之和最大值,

               因此當剩余數組下標為i到j時,

               當第一個人取第i個元素之后,第二個人也在試圖獲取i+1到j之間的子數組之和最大dp[i+1][j],此時第一個人能夠在i到j之間獲取的最終子數組之和為

               nums[i] + sum[i+1][j] - dp[i+1][j]           // 后半部分表示第二個人獲取最大子數組以后,剩余的字數組之和,也是第一個人只能選擇的子數組

               遞推公式如下:

               當第一個人獲取第i個元素時,dp[i][j] = nums[i] + sum[i+1][j] - dp[i+1][j] = dp_left

               當第一個人獲取第j個元素時,dp[i][j] = nums[j] + sum[i][j-1] - dp[i][j-1]  = dp_right

               第一個人想獲勝,因此dp[i][j] = max(dp_left, dp_right)

               當i == j時,只有一種選擇,dp[i][j] = nums[i]

               當i == j-1 時,只有兩種選擇,dp[i][j] = max(nums[i], nums[j])

               i到j之間的數組之和可以表示為sum[i][j] = sum[0][j] - sum[0][i-1] = sum(j) - sum(i-1)

               

【AC代碼】

class Solution3 {    public:        bool PredictTheWinner(std::vector<int>& nums) {            std::vector<std::vector<int> > dp(nums.size(), std::vector<int>(nums.size()));            std::vector<int> prefix_sum(nums.size()+1);            prefix_sum[0] = 0;            for (int i = 0; i < nums.size(); ++i) {                prefix_sum[i+1] = prefix_sum[i] + nums[i]; //下標從i+1開始            }            for (int len = 1; len <= nums.size(); ++len) {                for(int lhs = 0; lhs + len - 1 < nums.size(); ++lhs) {                    int rhs = lhs + len - 1;                    if (lhs == rhs) {                        dp[lhs][rhs] = nums[lhs];                    }                    else if(lhs == rhs - 1) {                        dp[lhs][rhs] = std::max(nums[lhs], nums[rhs]);                    }                    else {                        int dp_left = nums[lhs] + prefix_sum[rhs+1] - prefix_sum[lhs+1] - dp[lhs+1][rhs];                        int dp_right = nums[rhs] + prefix_sum[rhs] - prefix_sum[lhs] - dp[lhs][rhs-1];                        dp[lhs][rhs] = std::max(dp_left, dp_right);                    }                }            }            return 2 * dp[0][nums.size()-1] >= prefix_sum.back();            //return dp[0][nums.size()-1] >= prefix_sum.back() / 2 + prefix_sum.back() % 2;        }};參考資料:

https://discuss.leetcode.com/topic/76327/c-dp-solution-with-explanation

https://discuss.leetcode.com/topic/76472/clean-3ms-c-dp-solution-with-detailed-explanation


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 夏河县| 凉城县| 都安| 论坛| 桃园县| 门源| 鹤峰县| 马尔康县| 襄城县| 华坪县| 隆德县| 安图县| 安化县| 云安县| 崇仁县| 永清县| 正定县| 德昌县| 桃园县| 三明市| 洛南县| 合水县| 即墨市| 申扎县| 西城区| 台州市| 临漳县| 宜昌市| 祥云县| 清镇市| 杭州市| 九台市| 关岭| 德兴市| 澜沧| 贵定县| 甘孜| 桑日县| 青神县| 宜良县| 崇左市|