第九周(Dynamic ProgrammingIII)
目录:
- 本周完成题目
- 主要过程思路
- 相关代码
一、本周完成题目
本周共完成2道题目,2道Medium。主要是继续针对于所学的Dynamic Programming选择了一些题目进行练习。
具体完成题目及难度如下表:
# | Title | Difficulty |
---|---|---|
338 | Counting Bits | Medium |
486 | Predict the Winner | Medium |
题目内容
1、Counting Bits
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1’s in their binary representation and return them as an array.
Example:
For num = 5 you should return [0,1,1,2,1,2].
Follow up:
It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
Space complexity should be O(n).
Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
题目大意:给定一个数字num,判断0~num的每个数字二进制之后的位数中有几个1(时间复杂度为O(n))。
2、Predict the Winner
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: False
Explanation: 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: True
Explanation: 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.
题目大意:有一组数列,2个玩家可以选择数列头尾的数字。被选过的数字不能再选。按选的数字的总和判断,求player1 是否能赢。
二、主要过程思路
本周的题目使用到了Dynamic Programming的思想,简单来说需要从逐步到整体,动态操作最后得到需要的结果。
1、Counting Bits:
本题比较简单。主要的思路是已经计算过的部分的重用问题。用vectorres保存最后的结果。抛去最后一位。res[i]=res[i>>1]+i%2。也就是说,从较小的数字计算。之后的数字可以重用这些较小的数字。
以7为例。写成2进制结果是111。7>>1结果为3(011)。res[3]的值为2,加上最后一位的1得到的结果为3。
2、Predict the Winner:
参考代码
依然是动态规划的方式。设定一个dp[i][j]数组来保存从i到j,play1-play2的值,最后只需要判断这个值是否大于等于0即可。
具体而言,首先对于dp[i][i]进行初始化,使其等于num[i]。之后对于每一组进行操作。根据定义,dp’=dp-(sum-dp).根据这个式子进行转化,可以得到一个递归式:
max(nums[j] - dp’(i, j-1), nums[i] - dp’(i+1, j))递推过程如下:
dp'(i, j) = dp(i, j) - ( sum(i, j) - dp(i, j) ) = 2dp(i, j) - sum(i, j)
= 2 * max( sum(i, j) - dp(i, j-1), sum(i, j) - dp(i+1, j) ) - sum(i, j)
= max(sum(i, j) - 2*dp(i, j-1), sum(i, j) - 2*dp(i+1, j) )
= max(sum(i, j) - ( dp'(i, j-1) + sum(i, j-1) ), sum(i, j) - ( dp'(i+1, j) + sum(i+1, j)))
= max(sum(i, j) - sum(i, j-1) - dp'(i, j-1), sum(i, j) - sum(i+1, j) - dp'(i+1, j))
= max(nums[j] - dp'(i, j-1), nums[i] - dp'(i+1, j))
三、相关代码
Counting Bits
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res(num+1,0);
for(int i=0;i<=num;i++){
res[i]=res[i>>1]+i%2;
}
return res;
}
};
Predict the Winner
class Solution {
public:
bool PredictTheWinner(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> dp(n, vector<int>(n));
for(int i=0;i<n;i++){
dp[i][i]=nums[i];
}
for(int i=1;i<n;i++){
for(int j=0;j+i<n;j++){
dp[j][j+i]= max(nums[j+i]-dp[j][j+i-1], nums[j]-dp[j+1][j+i]);
}
}
return dp[0][n-1]>=0;
}
};