本文已参与「新人创作礼」活动,一起开启掘金创作之路。
第 73 场双周赛
题目
6024.数组中紧跟 key 之后出现最频繁的数字
题目大意
给你一个下标从 0 开始的整数数组 nums ,同时给你一个整数 key ,它在 nums 出现过。
统计 在 nums 数组中紧跟着 key 后面出现的不同整数 target 的出现次数。换言之,target 的出现次数为满足以下条件的 i 的数目:
0 <= i <= n - 2nums[i] == key且nums[i + 1] == target。
请你返回出现 最多 次数的 target 。测试数据保证出现次数最多的 target 是唯一的。
样例
数据规模
思路
太久没做题和打比赛了。第一题就WA了两次。
一开始题读错了:意外只要在之后就可以了,没有意识到两个必须挨着。
考虑使用map<int,int>mp,记录所有元素的数量,然后遍历nums保证nums[i]==key,然后取出现数量最多的nums[i+1],它就是所要求的target。
代码
class Solution {
public:
int mostFrequent(vector<int>& nums, int key) {
map<int,int>mp;
for(auto it:nums){
mp[it]++;
}
int opt=0,maxx=0;
for(int i=0;i<nums.size();i++){
if(nums[i]==key){
if(i+1<nums.size()&&maxx<mp[nums[i+1]]){
maxx=mp[nums[i+1]];
opt=nums[i+1];
}
}
}
return opt;
}
};
题目
5217.将杂乱无章的数字排序
题目大意
给你一个下标从 0 开始的整数数组 mapping ,它表示一个十进制数的映射规则,mapping[i] = j 表示这个规则下将数位 i 映射为数位 j 。
一个整数 映射后的值 为将原数字每一个数位 i (0 <= i <= 9)映射为 mapping[i] 。
另外给你一个整数数组 nums ,请你将数组 nums 中每个数按照它们映射后对应数字非递减顺序排序后返回。
注意:
- 如果两个数字映射后对应的数字大小相同,则将它们按照输入中的 相对顺序 排序。
nums中的元素只有在排序的时候需要按照映射后的值进行比较,返回的值应该是输入的元素本身。
样例
数据规模
思路
这一题又WA了一次:原因是在进行数字分解的时候没有考虑的情况。
定义了一个结构体Node用来记录原来的值p,出现的下标位置id和映射之后的值w。
定义排序顺序:将数组 nums 中每个数按照它们映射后对应数字非递减顺序排序,如果两个数字映射后对应的数字大小相同,则将它们按照输入中的 相对顺序 排序。
然后将nums中的数字进行分解并且映射,存储到Node数组中,进行排序,然后直接返回排序之后的结果即可。
代码
struct Node{
int w,id,p;
};
bool cmp(Node x,Node y){
if(x.w==y.w)return x.id<y.id;
return x.w<y.w;
}
class Solution {
public:
Node a[30000+50];
vector<int> sortJumbled(vector<int>& mapping, vector<int>& nums) {
int cnt=0;
for(auto it:nums){
vector<int>b;
int x=it,y=0;
if(it==0){
cnt++;
a[cnt].id=cnt;a[cnt].w=mapping[0];a[cnt].p=it;
continue;
}
while(x){
int q=x%10;
x/=10;
b.push_back(q);
}
for(int i=b.size()-1;i>=0;i--){
int q=mapping[b[i]];
y=y*10+q;
}
cnt++;
a[cnt].id=cnt;a[cnt].w=y;a[cnt].p=it;
}
sort(a+1,a+1+cnt,cmp);
vector<int>ans;
for(int i=1;i<=cnt;i++)ans.push_back(a[i].p);
return ans;
}
};
题目
5300.有向无环图中一个节点的所有祖先
题目大意
给你一个正整数 n ,它表示一个 有向无环图 中节点的数目,节点编号为 0 到 n - 1 (包括两者)。
给你一个二维整数数组 edges ,其中 edges[i] = [fromi, toi] 表示图中一条从 fromi 到 toi 的单向边。
请你返回一个数组 answer,其中 answer[i]是第 i 个节点的所有 祖先 ,这些祖先节点 升序 排序。
如果 u 通过一系列边,能够到达 v ,那么我们称节点 u 是节点 v 的 祖先 节点。
样例
数据规模
思路
极限情况也就是个点,不超过条边,直接考虑每一个点出发能到达哪些点。
具体怎么考虑呢?
比如条件给定了有向边,那么就说明是的祖先,那么我们建边就可以反向考虑建边,从点出发,可以到达点。
那么对于所有的边都像上述一样反向建边,然后从任意一点出发,那么它可以遍历到的所有点都是点的祖先(并且数据保证了不出现自环),然后将出现的点假如到vector数组中,保证从小到大的顺序即可。
代码
class Solution {
public:
vector<int>e[1000+50];
int vis[1000+50];
void dfs(int x,int f){
vis[x]=1;
for(int i=0;i<e[x].size();i++){
if(!vis[e[x][i]]){
dfs(e[x][i],x);
}
}
}
vector<vector<int>> getAncestors(int n, vector<vector<int>>& edges) {
for(int i=0;i<edges.size();i++){
for(int j=0;j<edges[i].size();j++){
int x=edges[i][0],y=edges[i][1];
e[y].push_back(x);
}
}
vector<vector<int> >ans;
for(int i=0;i<n;i++){
memset(vis,0,sizeof(vis));
dfs(i,i);
vector<int>a;
for(int j=0;j<n;j++){
if(i==j||!vis[j])continue;
a.push_back(j);
}
ans.push_back(a);
}
return ans;
}
};
题目
5237.得到回文串的最少操作次数
题目大意
给你一个只包含小写英文字母的字符串 s 。
每一次 操作 ,你可以选择 s 中两个 相邻 的字符,并将它们交换。
请你返回将 s 变成回文串的 最少操作次数 。
注意 ,输入数据会确保 s 一定能变成一个回文串。
样例
数据规模
思路
对于字符串能否变成回文串 ,判断两种情况
- 从右边找不到对应的字符:
- 字符串长度为偶数,不能有数量为的字符
- 字符串长度为奇数,只能有一个数量为的字符
- 从右边能找到对应的字符:
- 这时候就把这个字符移动到左边字符对称的右边的位置,前边和后边的这两个字符分别向后和向前移动
问题就转变为了:每次完成字符串(......)转化为x(......)x,然后再转化为xy(......)yx,直到变成对称的过程。
代码:
代码
class Solution {
public:
int minMovesToMakePalindrome(string s) {
int n=s.length();
int k=n-1,flag,ans;
ans=flag=0;
for(int i=0;i<k;i++){
for(int j=k;j>=i;j--){
if(j==i){
flag=1;
ans=ans+n/2-i;
}
else if(s[i]==s[j]){
for(int o=j;o<k;o++){
swap(s[o],s[o+1]);
ans++;
}
k--;
break;
}
}
}
return ans;
}
};