0
点赞
收藏
分享

微信扫一扫

第 73 场双周赛

ZGtheGreat 2022-03-11 阅读 40
leetcode

第 73 场双周赛

题目

6024.数组中紧跟 key 之后出现最频繁的数字

题目大意

给你一个下标从 0 开始的整数数组 nums ,同时给你一个整数 key ,它在 nums 出现过。

统计nums 数组中紧跟着 key 后面出现的不同整数 target 的出现次数。换言之,target 的出现次数为满足以下条件的 i 的数目:

  • 0 <= i <= n - 2
  • nums[i] == key
  • nums[i + 1] == target

请你返回出现 最多 次数的 target 。测试数据保证出现次数最多的 target 是唯一的。

样例

image-20220306170814801

数据规模

image-20220306170823731

思路

太久没做题和打比赛了。第一题就WA了两次。

一开始题读错了:意外只要 t a r g e t target target k e y key key之后就可以了,没有意识到两个必须挨着。

考虑使用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

一个整数 映射后的值 为将原数字每一个数位 i0 <= i <= 9)映射为 mapping[i]

另外给你一个整数数组 nums ,请你将数组 nums 中每个数按照它们映射后对应数字非递减顺序排序后返回。

注意:

  • 如果两个数字映射后对应的数字大小相同,则将它们按照输入中的 相对顺序 排序。
  • nums 中的元素只有在排序的时候需要按照映射后的值进行比较,返回的值应该是输入的元素本身。

样例

image-20220306171446191

数据规模

image-20220306171455627

思路

这一题又WA了一次:原因是在进行数字分解的时候没有考虑 0 0 0的情况。

定义了一个结构体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 ,它表示一个 有向无环图 中节点的数目,节点编号为 0n - 1 (包括两者)。

给你一个二维整数数组 edges ,其中 edges[i] = [fromi, toi] 表示图中一条从 fromitoi 的单向边。

请你返回一个数组 answer,其中 answer[i]是第 i 个节点的所有 祖先 ,这些祖先节点 升序 排序。

如果 u 通过一系列边,能够到达 v ,那么我们称节点 u 是节点 v祖先 节点。

样例

image-20220306172008663

image-20220306172016622

数据规模

image-20220306172039894

思路

极限情况也就是 1000 1000 1000个点,不超过 2000 2000 2000条边,直接考虑每一个点 i i i出发能到达哪些点。

具体怎么考虑呢?

比如条件给定了有向边 a − > b a->b a>b,那么就说明 a a a b b b的祖先,那么我们建边就可以反向考虑建边 b − > a b->a b>a,从点 b b b出发,可以到达点 a a a

那么对于所有的边都像上述一样反向建边,然后从任意一点 i i i出发,那么它可以遍历到的所有点都是点 i i i的祖先(并且数据保证了不出现自环),然后将出现的点假如到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 一定能变成一个回文串。

样例

image-20220306172634342

数据规模

image-20220306172641469

思路

对于字符串能否变成回文串 ,判断两种情况

  • 从右边找不到对应的字符
    • 字符串长度为偶数,不能有数量为 1 1 1的字符
    • 字符串长度为奇数,只能有一个数量为 1 1 1的字符
  • 从右边能找到对应的字符
    • 这时候就把这个字符移动到左边字符对称的右边的位置,前边和后边的这两个字符分别向后和向前移动

问题就转变为了:每次完成字符串(......)转化为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;
    }
};
举报

相关推荐

0 条评论