leetcode周赛 232

A:水题,给定两个字符串,问能否只交换一次使得两字符串相等。

 解法1:记录两字符串不相等的位置。

 1 class Solution {
 2 public:
 3     bool areAlmostEqual(string s1, string s2) {
 4         int n=s1.length();
 5         int cnt=0;
 6         int a=-1,b=-1;
 7         for(int i=0;i<n;i++){
 8             if(s1[i]!=s2[i]){
 9                 cnt++;
10                 if(cnt==1) a=i;
11                 else if(cnt==2) b=i;
12             }
13         }
14         if(cnt==0||(cnt==2&&s1[a]==s2[b]&&s1[b]==s2[a])){
15             return true;
16         }
17         return false;
18     }
19 };

 解法二:枚举s1所有可能的交换两个位置的情况,判断两字符串是否相等,时间复杂度为O(n^3)

 1 class Solution {
 2 public:
 3     bool areAlmostEqual(string s1, string s2) {
 4         if(s1==s2) return true;
 5         int n=s1.size();
 6         for(int i=0;i<n;i++){
 7             for(int j=0;j<i;j++){
 8                 swap(s1[i],s1[j]);
 9                 if(s1==s2) return true;
10                 swap(s1[i],s1[j]);
11             }
12         }
13         return false;
14     }
15 };

 

 

B:给定一个星型图,要你找中心点。

枚举每个节点的度,如果超过1,则是中心点。

 1 class Solution {
 2 public:
 3     int findCenter(vector<vector<int>>& edges) {
 4         unordered_map<int,int> d;
 5         for(auto &x:edges){
 6             int a=x[0],b=x[1];
 7             if(++d[a]>=2) return a;
 8             if(++d[b]>=2) return b;
 9         }
10         return -1;
11     }
12 };

 

 

C:给定n个班级的不通过的学生和通过的学生

  以及n个尖子生。问将尖子生分给各个班级后,最大平均通过率是多少。

( x + 1 ) / ( y + 1 )  -  x / y =  ( y - x ) / ( y * ( y + 1 ) )

所以若以向某个班级添加的人数为x,增加的通过率为y建立函数的话,该函数是单调递减

而我们希望最大化平均通过率,n是不变的,也就是最大化通过率之和。

那么我们希望每次添加的人的增量是最大的。

这就是典型的多路归并的模型。

 1 class Solution {
 2 public:
 3     double maxAverageRatio(vector<vector<int>>& classes, int k) { 
 4         struct Node{
 5             double s;
 6             int a,b;
 7             Node(double _s,int _a,int _b):s(_s),a(_a),b(_b){}
 8             bool operator<(const Node& t)const {
 9                 return s<t.s;
10             }
11             bool operator>(const Node& t)const {
12                 return s>t.s;
13             }
14         };
15         priority_queue<Node,vector<Node>,less<Node>> q;
16         double res=0;
17         for(auto &x:classes){
18             int a=x[0],b=x[1];
19             double s=(b-a)/(b*(b+1.0));
20             res+=a/(b+0.0);
21             q.push({s,a,b});
22         }
23         while(k--){
24             Node t=q.top();
25             q.pop();
26             res+=t.s;
27             int a=t.a+1,b=t.b+1;
28             double s=(b-a)/(b*(b+1.0));
29             q.push({s,a,b});
30         }
31         return res/classes.size();
32     }
33 };

 

 

D:对于每一段答案序列,其中必然有一个或者多个最小的数。

  所以如果我们对每一个数都向其两边扩散,必然会将最终答案包括在内。暴力做的复杂度为O(n^2)。

  我们可以借助单调栈这个数据结构,对于每一个数,求出大于等于他的左边最远和右边最远,用时O(n),然后就可以直接计算答案了。总时间复杂度为O(n)

 1 class Solution {
 2 public:
 3     int maximumScore(vector<int>& nums, int k) {
 4         int n=nums.size();
 5         vector<int> h(n+2,-1),l(n+2),r(n+2),stk(n+2);
 6         for(int i=1;i<=n;i++){
 7             h[i]=nums[i-1];
 8         }
 9         stk[0]=0;
10         int tt=0;
11         for(int i=1;i<=n;i++){
12             while(h[stk[tt]]>=h[i]) tt--;
13             l[i]=stk[tt];
14             stk[++tt]=i;
15         }
16         stk[0]=n+1;
17         tt=0;
18         for(int i=n;i>0;i--){
19             while(h[stk[tt]]>=h[i]) tt--;
20             r[i]=stk[tt];
21             stk[++tt]=i;
22         }
23         int res=0;
24         k++;
25         for(int i=1;i<=n;i++){
26             if(l[i]<k&&r[i]>k){
27                 res=max(res,h[i]*(r[i]-l[i]-1));
28             }
29         }
30         return res;
31     }
32 };

 

posted on 2021-03-15 17:43  greenofyu  阅读(40)  评论(0编辑  收藏  举报