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

首頁 > 學院 > 開發(fā)設計 > 正文

486. Predict the Winner

2019-11-11 02:23:47
字體:
供稿:網(wǎng)友

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、該問題是兩個人交替從一個數(shù)組兩端獲取一個數(shù)字,每次每個人只能獲取一個,最終獲取的數(shù)字之和最大的獲勝,問第一個人能否獲勝

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

        一種是建立二叉樹方法:

        A、建立兩顆二叉樹,第一顆的根節(jié)點是第一個數(shù)字,第二顆的根節(jié)點是第二個數(shù)字

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

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

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

        另一種是動態(tài)規(guī)劃算法:

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

               依次交替直到取完所有數(shù)字

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

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

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

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

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

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

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

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

               因此當剩余數(shù)組下標為i到j時,

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

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

               遞推公式如下:

               當?shù)谝粋€人獲取第i個元素時,dp[i][j] = nums[i] + sum[i+1][j] - dp[i+1][j] = dp_left

               當?shù)谝粋€人獲取第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之間的數(shù)組之和可以表示為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


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 自治县| 宣威市| 台北市| 灵宝市| 天津市| 大方县| 徐闻县| 台山市| 微山县| 津市市| 北宁市| 阳原县| 晋宁县| 扎赉特旗| 萨迦县| 亳州市| 青神县| 深州市| 大石桥市| 玉环县| 鸡西市| 额济纳旗| 临城县| 车险| 大关县| 龙江县| 海晏县| 巴里| 金山区| 密云县| 乌海市| 开阳县| 旅游| 明水县| 吴江市| 双辽市| 舟曲县| 富顺县| 黄浦区| 湟源县| 辽宁省|