30,419
社区成员
发帖
与我相关
我的任务
分享给你一个下标从 0 开始的整数数组 nums ,你必须将数组划分为一个或多个 连续 子数组。
如果获得的这些子数组中每个都能满足下述条件 之一 ,则可以称其为数组的一种 有效 划分:
子数组 恰 由 2 个相等元素组成,例如,子数组 [2,2] 。
子数组 恰 由 3 个相等元素组成,例如,子数组 [4,4,4] 。
子数组 恰 由 3 个连续递增元素组成,并且相邻元素之间的差值为 1 。例如,子数组 [3,4,5] ,但是子数组 [1,3,5] 不符合要求。
如果数组 至少 存在一种有效划分,返回 true ,否则,返回 false 。
const int N=1e5+10; class Solution { public: int f[N]; bool validPartition(vector<int>& nums) { memset(f,0,sizeof(f)); int n=nums.size(); vector<int> a(n+1,0); for(int i=0;i<n;i++) a[i+1]=nums[i]; f[0]=1; for(int i=2;i<=n;i++){ if(a[i]==a[i-1]) f[i]|=f[i-2]; if(i>=3&&a[i]==a[i-1]&&a[i-1]==a[i-2]) f[i]|=f[i-3]; if(i>=3&&a[i]==a[i-1]+1&&a[i-1]==a[i-2]+1) f[i]|=f[i-3]; } return f[n]; } };
给你一个由小写字母组成的字符串 s ,和一个整数 k 。如果满足下述条件,则可以将字符串 t 视作是 理想字符串 :
t 是字符串 s 的一个子序列。
t 中每两个 相邻 字母在字母表中位次的绝对差值小于或等于 k 。
返回 最长 理想字符串的长度。字符串的子序列同样是一个字符串,并且子序列还满足:可以经由其他字符串删除某些字符(也可以不删除)但不改变剩余字符的顺序得到。
注意:字母表顺序不会循环。例如,'a' 和 'z' 在字母表中位次的绝对差值是 25 ,而不是 1 。
const int N=1e5+10; class Solution { public: int f[N][30]; int longestIdealString(string s, int k) { memset(f,0,sizeof(f)); int n=s.size(); vector<int> a; a.push_back(150); for(auto&x:s){ a.push_back(x-'a'); } f[0][0]=0; int res=0; for(int i=1;i<=n;i++){ int x=a[i]; f[i][x]=1; for(int j=0;j<26;j++) f[i][j]=f[i-1][j]; for(int j=0;j<26;j++) { if(abs(x-j)<=k) f[i][x]=max(f[i][x],f[i-1][j]+1); } res=max(res,f[i][x]); } return res; } };
const int N=1010,mod=1e9+7; class Solution { public: int peopleAwareOfSecret(int n, int delay, int forget) { // memset(f,0,sizeof(f)); vector<int> f(n+1),g(n+1); f[1]=g[1]=1; for(int i=2;i<=n;i++){ int l=max(0,i-forget+1); int r=max(0,i-delay); f[i]=(g[r]-g[max(0,l-1)]+mod)%mod; g[i]=(f[i]+g[i-1])%mod; } return ((g[n]-g[max(0,n-forget)])+mod)%mod; } };在第 1 天,有一个人发现了一个秘密。
给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后,每天 给一个新的人 分享 秘密。同时给你一个整数 forget ,表示每个人在发现秘密 forget 天之后会 忘记 这个秘密。一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。
给你一个整数 n ,请你返回在第 n 天结束时,知道秘密的人数。由于答案可能会很大,请你将结果对 109 + 7 取余 后返回。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-people-aware-of-a-secret
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
给你一个下标从 0 开始的 m x n 整数矩阵 grid 和一个整数 k 。你从起点 (0, 0) 出发,每一步只能往 下 或者往 右 ,你想要到达终点 (m - 1, n - 1) 。
请你返回路径和能被 k 整除的路径数目,由于答案可能很大,返回答案对 109 + 7 取余 的结果。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/paths-in-matrix-whose-sum-is-divisible-by-k
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。const int N=1010,mod=1e9+7; class Solution { public: int numberOfPaths(vector<vector<int>>& grid, int d) { int n=grid.size(),m=grid[0].size(); vector<vector<int>> a(n+1,vector<int>(m+1,0)); int f[n+1][m+1][50]; memset(f,0,sizeof(f)); for(int i=0;i<n;i++){ for(int j=0;j<m;j++) a[i+1][j+1]=grid[i][j]; } f[1][1][a[1][1]%d]=1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ for(int k=0;k<d;k++){ if(i==1&&j==1) continue; if(i-1>=1)f[i][j][k]=(f[i][j][k]+f[i-1][j][(((k-a[i][j])%d)+d)%d])%mod; if(j-1>=1)f[i][j][k]=(f[i][j][k]+f[i][j-1][(((k-a[i][j])%d)+d)%d])%mod; } } } return f[n][m][0]; } };
给你一个 m x n 的整数网格图 grid ,你可以从一个格子移动到 4 个方向相邻的任意一个格子。
请你返回在网格图中从 任意 格子出发,达到 任意 格子,且路径中的数字是 严格递增 的路径数目。由于答案可能会很大,请将结果对 109 + 7 取余 后返回。
如果两条路径中访问过的格子不是完全相同的,那么它们视为两条不同的路径。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-increasing-paths-in-a-grid
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。const int N=1010,mod=1e9+7; class Solution { public: int f[N][N]; int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1}; int n,m; int dfs(int x,int y,vector<vector<int>>& grid){ if(f[x][y]!=-1) return f[x][y]; if(x<0||y<0||x>n||y>m) return 1; f[x][y]=1; for(int i=0;i<4;i++){ int tx=x+dx[i],ty=y+dy[i]; if(tx<=0||tx>n||ty<=0||ty>m) continue; if(grid[x][y]<grid[tx][ty]) { f[x][y]=(f[x][y]+dfs(tx,ty,grid))%mod; } } return f[x][y]; } int countPaths(vector<vector<int>>& grid) { memset(f,-1,sizeof(f)); int res=0; n=grid.size(),m=grid[0].size(); vector<vector<int>> g(n+1,vector<int>(m+1,0)); for(int i=0;i<n;i++){ for(int j=0;j<m;j++) g[i+1][j+1]=grid[i][j]; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ res=(res+dfs(i,j,g))%mod; } } return res; } };
给你一个字符串 s 和一个 正 整数 k 。
从字符串 s 中选出一组满足下述条件且 不重叠 的子字符串:
每个子字符串的长度 至少 为 k 。
每个子字符串是一个 回文串 。
返回最优方案中能选择的子字符串的 最大 数目。子字符串 是字符串中一个连续的字符序列。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-number-of-non-overlapping-palindrome-substrings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。const int N=4010;
class Solution {
public:
int maxPalindromes(string s, int k) {
int n=s.size();
bool st[N][N];
memset(st,0,sizeof(st));
int f[n+10];
memset(f,0,sizeof(f));
s="?"+s;
for(int i=1;i<=2*n-1;i++){
int l=i/2,r=i/2+(i%2);
while(l>=1&&r<=n&&s[l]==s[r]){
st[l][r]=true;
l--;
r++;
}
}
f[0]=0;
for(int i=1;i<=n;i++) st[i][i]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
f[i]=max(f[i],f[i-1]);
if(st[j][i]&&i-j+1>=k) f[i]=max(f[i],f[j-1]+1);
}
}
return f[n];
}
};
给你一个仅由小写英文字母组成的字符串 s 。在一步操作中,你可以:
删除 整个字符串 s ,或者
对于满足 1 <= i <= s.length / 2 的任意 i ,如果 s 中的 前 i 个字母和接下来的 i 个字母 相等 ,删除 前 i 个字母。
例如,如果 s = "ababc" ,那么在一步操作中,你可以删除 s 的前两个字母得到 "abc" ,因为 s 的前两个字母和接下来的两个字母都等于 "ab" 。返回删除 s 所需的最大操作数。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-deletions-on-a-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。class Solution { public: int deleteString(string s) { int n=s.size(); s="?"+s; int lcp[n+10][n+10]; memset(lcp,0,sizeof(lcp)); for(int i=n;i>=1;i--){ for(int j=n;j>=1;j--){ if(s[i]==s[j]) lcp[i][j]=lcp[i+1][j+1]+1; else lcp[i][j]=0; } } int f[n+10]; memset(f,0,sizeof(f)); f[n+1]=0; for(int i=n;i>=1;i--){ f[i]=1; for(int j=1;i+2*j-1<=n;j++){ if(lcp[i][i+j]>=j) f[i]=max(f[i],1+f[i+j]); } } return f[1]; } };
如果一个正整数每一个数位都是 互不相同 的,我们称它是 特殊整数 。
给你一个 正 整数
n,请你返回区间[1, n]之间特殊整数的数目。class Solution { public: int f[15][1024]; int a[15]; int len; int dfs(int pos,int pre,int lead,int limit,int cnt){ if(!pos) return !lead; if(!limit&&!lead&&f[pos][cnt]!=-1) return f[pos][cnt]; int res=0,up=limit?a[pos]:9; for(int i=0;i<=up;i++){ if(cnt>>i&1) continue; int c=cnt; if(lead&&!i){ res+=dfs(pos-1,0,lead&&!i,limit&&i==up,cnt); } else{ c|=1<<i; res+=dfs(pos-1,i,lead&&!i,limit&&i==up,c); } } return limit?res:(lead?res:f[pos][cnt]=res); } int cal(int x){ len=0; memset(f,-1,sizeof(f)); while(x){ a[++len]=x%10; x/=10; } return dfs(len,0,1,1,0); } int countSpecialNumbers(int n) { //memset(f,0,sizeof(f)); return cal(n); } };class Solution: def countSpecialNumbers(self, n: int) -> int: s = str(n) @cache def f(i: int, mask: int, is_limit: bool, is_num: bool) -> int: if i == len(s): return int(is_num) res = 0 if is_num==False: # 可以跳过当前数位 res = f(i + 1, mask, False, False) up = int(s[i]) if is_limit else 9 for d in range(0,up+1): # 枚举要填入的数字 d if mask >> d & 1 == 0: # d 不在 mask 中 res += f(i + 1, mask | (1 << d), is_limit and d == up, True) return res return f(0, 0, True, False)
给你一个整数数组 nums 和一个整数 k 。
找到 nums 中满足以下要求的最长子序列:
子序列 严格递增
子序列中相邻元素的差值 不超过 k 。
请你返回满足上述要求的 最长子序列 的长度。子序列 是从一个数组中删除部分元素后,剩余元素不改变顺序得到的数组。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-increasing-subsequence-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。const int N=1e5+10; class Solution { public: struct node{ int l,r; int mx; }tr[N*4]; void pushup(int u){ tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx); } void build(int u,int l,int r){ tr[u]={l,r,0}; if(l==r){ return ; } else{ int mid=(l+r)>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); } } void modify(int u,int x,int c){ if(tr[u].l==tr[u].r&&x==tr[u].l){ tr[u].mx=max(tr[u].mx,c); return; } else{ int mid=(tr[u].l+tr[u].r)>>1; if(x<=mid) modify(u<<1,x,c); else modify(u<<1|1,x,c); pushup(u); } } int query(int u,int l,int r){ if(tr[u].l>=l&&tr[u].r<=r){ return tr[u].mx; } else{ int mid=(tr[u].l+tr[u].r)>>1; int res=0; if(l<=mid) res=max(res,query(u<<1,l,r)); if(r>mid) res=max(res,query(u<<1|1,l,r)); return res; } } int lengthOfLIS(vector<int>& nums, int k) { memset(tr,0,sizeof(tr)); build(1,0,100000); int n=nums.size(); vector<int> a(n+1,0); for(int i=0;i<n;i++) a[i+1]=nums[i]; int f[n+10]; memset(f,0,sizeof(f)); int res=0; for(int i=1;i<=n;i++){ int x=a[i]; f[i]=1; int t=query(1,max(0,x-k),max(0,x-1)); f[i]=max(f[i],t+1); modify(1,x,f[i]); res=max(res,f[i]); } return res; } };
给你一棵 二叉树 的根节点 root ,树中有 n 个节点。每个节点都可以被分配一个从 1 到 n 且互不相同的值。另给你一个长度为 m 的数组 queries 。
你必须在树上执行 m 个 独立 的查询,其中第 i 个查询你需要执行以下操作:
从树中 移除 以 queries[i] 的值作为根节点的子树。题目所用测试用例保证 queries[i] 不 等于根节点的值。
返回一个长度为 m 的数组 answer ,其中 answer[i] 是执行第 i 个查询后树的高度。注意:
查询之间是独立的,所以在每个查询执行后,树会回到其 初始 状态。
树的高度是从根到树中某个节点的 最长简单路径中的边数 。来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/height-of-binary-tree-after-subtree-removal-queries
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public:unordered_map<TreeNode*,int> height; vector<int> res; int get_height(TreeNode*root){ if(root==nullptr) return 0; height[root]=1+max(get_height(root->left),get_height(root->right)); return height[root]; } void dfs(TreeNode*root,int depth,int res_h){ if(root==nullptr) return; res[root->val]=res_h; dfs(root->left,depth+1,max(res_h,depth+height[root->right])); dfs(root->right,depth+1,max(res_h,depth+height[root->left])); } vector<int> treeQueries(TreeNode* root, vector<int>& queries) { get_height(root); res.resize(height.size()+1); dfs(root,0,0); for(auto&q:queries) q=res[q]; return queries; } };
给你一个字符串 s ,每个字符是数字 '1' 到 '9' ,再给你两个整数 k 和 minLength 。
如果对 s 的分割满足以下条件,那么我们认为它是一个 完美 分割:
s 被分成 k 段互不相交的子字符串。
每个子字符串长度都 至少 为 minLength 。
每个子字符串的第一个字符都是一个 质数 数字,最后一个字符都是一个 非质数 数字。质数数字为 '2' ,'3' ,'5' 和 '7' ,剩下的都是非质数数字。
请你返回 s 的 完美 分割数目。由于答案可能很大,请返回答案对 109 + 7 取余 后的结果。一个 子字符串 是字符串中一段连续字符串序列。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-beautiful-partitions
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。const int mod=1e9+7; class Solution { public: int beautifulPartitions(string s, int k, int minLength) { int n=s.size(); s="?"+s; int f[n+10]; int g[n+10]; memset(f,0,sizeof(f)); vector<int> pirmes(10,0); pirmes[2]=1;pirmes[3]=1;pirmes[5]=1;pirmes[7]=1; f[0]=1; for(int i=1;i<=k;i++){ memcpy(g,f,sizeof(f)); memset(f,0,sizeof(f)); int v=0; for(int j=1;j<=n;j++){ if(j-minLength+1>=1&&pirmes[s[j-minLength+1]-'0']) v=(v+g[j-minLength])%mod; if(pirmes[s[j]-'0']==0) f[j]=v; } } return f[n]; } };
给你一个正整数数组 nums 和一个整数 k 。
分区 的定义是:将数组划分成两个有序的 组 ,并满足每个元素 恰好 存在于 某一个 组中。如果分区中每个组的元素和都大于等于 k ,则认为分区是一个好分区。
返回 不同 的好分区的数目。由于答案可能很大,请返回对 109 + 7 取余 后的结果。
如果在两个分区中,存在某个元素 nums[i] 被分在不同的组中,则认为这两个分区不同。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-great-partitions
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。const int mod=1e9+7; class Solution { public: int countPartitions(vector<int>& nums, int k) { if(accumulate(nums.begin(),nums.end(),0ll)<2*k) return 0; //第一个分组或第二个分组和小于k int ans=1; int f[k]; memset(f,0,sizeof(f)); f[0]=1; for(auto&x:nums){ ans=ans*2%mod; for(int j=k-1;j>=x;j--) f[j]=(f[j]+f[j-x])%mod; } for(int x:f){ ans=(ans-x*2%mod+mod)%mod; } return ans; } };
X 轴上有一些机器人和工厂。给你一个整数数组 robot ,其中 robot[i] 是第 i 个机器人的位置。再给你一个二维整数数组 factory ,其中 factory[j] = [positionj, limitj] ,表示第 j 个工厂的位置在 positionj ,且第 j 个工厂最多可以修理 limitj 个机器人。
每个机器人所在的位置 互不相同 。每个工厂所在的位置也 互不相同 。注意一个机器人可能一开始跟一个工厂在 相同的位置 。
所有机器人一开始都是坏的,他们会沿着设定的方向一直移动。设定的方向要么是 X 轴的正方向,要么是 X 轴的负方向。当一个机器人经过一个没达到上限的工厂时,这个工厂会维修这个机器人,且机器人停止移动。
任何时刻,你都可以设置 部分 机器人的移动方向。你的目标是最小化所有机器人总的移动距离。
请你返回所有机器人移动的最小总距离。测试数据保证所有机器人都可以被维修。
注意:
所有机器人移动速度相同。
如果两个机器人移动方向相同,它们永远不会碰撞。
如果两个机器人迎面相遇,它们也不会碰撞,它们彼此之间会擦肩而过。
如果一个机器人经过了一个已经达到上限的工厂,机器人会当作工厂不存在,继续移动。
机器人从位置 x 到位置 y 的移动距离为 |y - x| 。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-total-distance-traveled
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。class Solution: def minimumTotalDistance(self, robot: List[int], factory: List[List[int]]) -> int: m=len(factory) n=len(robot) factory.append([-(10**10)]) robot.append(-(10**10)) robot.sort() factory.sort() f=[[inf]*(n+10) for _ in range(m+10)] for i in range(0,m+1): f[i][0]=0 for i in range(1,m+1): for j in range(1,n+1): cost=0 limit=factory[i][1] f[i][j]=min(f[i][j],f[i-1][j]) for k in range(j,0,-1): if j-limit>=k:break cost+=abs(robot[k]-factory[i][0]) f[i][j]=min(f[i][j],f[i-1][k-1]+cost) return f[m][n]