1337. 矩阵中战斗力最弱的 K 行
-
题目大意
n*m的矩阵,每行有1代表士兵,0代表平民,问战斗力最弱的k行(按战斗力输出)。 -
思路
-
code
class Solution {
#define N 110
struct node{
int num,index;
}a[N];
static bool cmp(struct node &a, struct node &b){
if(a.num==b.num) return a.index<b.index;
return a.num<b.num;
}
public:
vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
int n = mat.size();
int m = mat[0].size();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++) a[i].num+=mat[i][j],a[i].index=i;
}
sort(a,a+n,cmp);
vector<int> ans(k,0);
for(int i=0;i<k;i++) ans[i]=a[i].index;
return ans;
}
};
1338. 数组大小减半
- 题目大意
你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。返回 至少 能删除数组中的一半整数的整数集合的最小大小。 - 思路
贪心 今年可能删除出现次数多的。 - code
class Solution {
#define N 100005
static bool cmp(int a,int b){
return a>b;
}
public:
int minSetSize(vector<int>& arr) {
int n = arr.size();
int mp[N]={0};
for(int i=0;i<n;i++) mp[arr[i]]++;
sort(mp,mp+N,cmp);
int ans=0,tot=0;
for(int i=0;i<n;i++)
{
tot+=mp[i];cout<<tot<<endl;
if(tot>=n/2) return i+1;
}
return n;
}
};
1339. 分裂二叉树的最大乘积
- 题目大意
给定一颗二叉树,现在将其中的任意一条边删掉,求分开的两部分子树和的最大乘积。 - 思路
dfs 虽然给定的数据结构比较奇怪 但是还是一样的dfs就ok了 - code
/**
* 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 {
#define N 50005
#define ll long long
ll ans=0,tot=0;
void dfs(TreeNode* now)
{
if(!now) return;
tot+=now->val;
dfs(now->left);
dfs(now->right);
}
int dfs2(TreeNode* now)
{
if(!now) return 0;
int temp = dfs2(now->left)+dfs2(now->right)+now->val;
if(abs(ans*2-tot)>abs(temp*2-tot)) ans=temp;
return temp;
}
public:
int maxProduct(TreeNode* root) {
ll mod = 1000000007;
dfs(root);
dfs2(root);
return ans*(tot-ans)%mod;
}
};
1340. 跳跃游戏 V
- 题目大意
有长度为n的序列arr,每个点i可以跳到 i + x ( 0 < x < = d , i + x < n ) i+x(0<x<=d,i+x<n) i+x(0<x<=d,i+x<n)或者 i − x ( 0 < x < = d , i − x > = 0 ) i-x(0<x<=d,i-x>=0) i−x(0<x<=d,i−x>=0)并且要保证从 i i i到 x x x之间的数都要小于 a r r [ i ] arr[i] arr[i]。可以从任一点出发,问从某一点出发最多可以到达多少个点。 - 思路
dp[i]=max(dp[i],dp[x]+1),x为遍历(i-d,i+d)之间的合法的数。
那么我们要从哪里处罚是无从得知的,因此可以采用记忆化搜索方法。
注意遍历的顺序,要从离i最近的点开始,要不然答案是错的。 - code
class Solution {
#define N 1010
int dp[N]={0},st[N]={0};
int ans=0,n;
int dfs(int x,int d,vector<int>& arr)
{
if(st[x]) return dp[x];
st[x]=1;
for(int i=x-1;i>=max(0,x-d)&&arr[i]<arr[x];i--) dp[x]=max(dp[x],dfs(i,d,arr)+1);
for(int i=x+1;i<min(n,x+d+1)&&arr[i]<arr[x];i++) dp[x]=max(dp[x],dfs(i,d,arr)+1);
return dp[x];
}
public:
int maxJumps(vector<int>& arr, int d) {
n =arr.size();
for(int i=0;i<n;i++) dp[i]=1;
for(int i=0;i<n;i++) dp[i]=dfs(i,d,arr);
for(int i=0;i<n;i++) ans=max(ans,dp[i]);
for(int i=0;i<n;i++) cout<<dp[i]<<endl;
return ans;
}
};