1137. 第 N 个泰波那契数
https://leetcode-cn.com/contest/weekly-contest-147/problems/n-th-tribonacci-number/
泰波那契序列 Tn 定义如下:
T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2
给你整数 n,请返回第 n 个泰波那契数 Tn 的值。示例 1:
输入:n = 4
输出:4
解释:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4
示例 2:
输入:n = 25
输出:1389537提示:
0 <= n <= 37
答案保证是一个 32 位整数,即 answer <= 2^31 - 1。
做个递归或迭代打表都行
class Solution {
public:
int a[40]={0,1,1};
int tribonacci(int n)
{
if(n<3) return a[n];
else if(a[n]!=0) return a[n];
else return a[n]=tribonacci(n-1)+tribonacci(n-2)+tribonacci(n-3);
}
};
1138. 字母板上的路径
https://leetcode-cn.com/contest/weekly-contest-147/problems/alphabet-board-path/
我们从一块字母板上的位置 (0, 0) 出发,该坐标对应的字符为 board[0][0]。
在本题里,字母板为board = ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"].
我们可以按下面的指令规则行动:
如果方格存在,'U' 意味着将我们的位置上移一行;
如果方格存在,'D' 意味着将我们的位置下移一行;
如果方格存在,'L' 意味着将我们的位置左移一列;
如果方格存在,'R' 意味着将我们的位置右移一列;
'!' 会把在我们当前位置 (r, c) 的字符 board[r][c] 添加到答案中。
返回指令序列,用最小的行动次数让答案和目标 target 相同。你可以返回任何达成目标的路径。示例 1:
输入:target = "leet"
输出:"DDR!UURRR!!DDD!"
示例 2:
输入:target = "code"
输出:"RR!DDRR!UUL!R!"提示:
1 <= target.length <= 100
target 仅含有小写英文字母。
由board可知,字母是顺序排列的,所有求两字母差值,并对5求商和余数即可得两字母x和y轴的距离,分别按距离移动即可
要注意的是,字母‘z’单独在一行,为了不移动时超范围,先上下移再左右移。此外,当下移到第五行的时候须终止再在最后另行判断是否需下移到第六行。
class Solution {
public:
string alphabetBoardPath(string target)
{
string ans="";
int x=0,y=0;
for(int i=0;inx)
{
ans += 'U';
x--;
}
while(y>ny)
{
ans += 'L';
y--;
}
while(y
1139. 最大的以 1 为边界的正方形
https://leetcode-cn.com/contest/weekly-contest-147/problems/largest-1-bordered-square/
给你一个由若干 0 和 1 组成的二维网格 grid,请你找出边界全部由 1 组成的最大 正方形 子网格,并返回该子网格中的元素数量。如果不存在,则返回 0。
示例 1:
输入:grid = [[1,1,1],[1,0,1],[1,1,1]]
输出:9
示例 2:
输入:grid = [[1,1,0,0]]
输出:1提示:
1 <= grid.length <= 100
1 <= grid[0].length <= 100
grid[i][j] 为 0 或 1
因为最大100,可以n³遍历。
分别用left和up存储算上该位置左边和上边的连续的1的数量,再对每个位置分别遍历,验证满足正方形成立的条件(四条边相等),最后得出最大的正方形
class Solution {
public:
int largest1BorderedSquare(vector>& grid)
{
int left[102][102],up[102][102];
int ans=0,key=0;
for(int i=0;i
1140. 石子游戏 II
https://leetcode-cn.com/contest/weekly-contest-147/problems/stone-game-ii/
亚历克斯和李继续他们的石子游戏。许多堆石子 排成一行,每堆都有正整数颗石子 piles[i]。游戏以谁手中的石子最多来决出胜负。
亚历克斯和李轮流进行,亚历克斯先开始。最初,M = 1。
在每个玩家的回合中,该玩家可以拿走剩下的 前 X 堆的所有石子,其中 1 <= X <= 2M。然后,令 M = max(M, X)。
游戏一直持续到所有石子都被拿走。
假设亚历克斯和李都发挥出最佳水平,返回亚历克斯可以得到的最大数量的石头。示例:
输入:piles = [2,7,9,4,4]
输出:10
解释:
如果亚历克斯在开始时拿走一堆石子,李拿走两堆,接着亚历克斯也拿走两堆。在这种情况下,亚历克斯可以拿到 2 + 4 + 4 = 10 颗石子。
如果亚历克斯在开始时拿走两堆石子,那么李就可以拿走剩下全部三堆石子。在这种情况下,亚历克斯可以拿到 2 + 7 = 9 颗石子。
所以我们返回更大的 10。提示:
1 <= piles.length <= 100
1 <= piles[i] <= 10 ^ 4
这种博弈的问题,要假设双方都能取得当前情况下的最优解,用sum记录前缀和,用dp记录当M和从第n堆开始时能拿石子的最大数量,用动规做推导
当前该人已经拿到的数量加上剩下的石子中对方可以拿到的数量即为dp的值
class Solution {
public:
int sum[102],dp[102][102];
int N;
int solve(int n,int M,vector& piles)
{
if(n>=N) return 0;
if(dp[M][n]) return dp[M][n];
int ans = 0,count=0;
for(int i=1;i<=2*M;i++)
{
if(i+n-1>=N) break;
count+=piles[i+n-1];
ans = max(ans,sum[N]-sum[i+n]-solve(i+n,max(i,M),piles)+count);
}
return dp[M][n]= ans;
}
int stoneGameII(vector& piles)
{
N = piles.size();
for(int i=1;i<=N;i++) sum[i]= sum[i-1]+piles[i-1];
return solve(0,1,piles);
}
};
t