Leetcode 232场周赛总结

这次周赛应该是今年最简单的一次了,然而我还是没有AK
下面总结以下这次错误与教训。

第一题

(题号5701):
在这里插入图片描述
在这里插入图片描述
简单题,但是WA了一次
一开始以为找到相同字母换一下就完事了,交了一发才知道事情不简单。
然后开始统计不同字母的个数,
若为1或者大于2,则肯定交换不了;
若为0则肯定交换的了;
若为2则交换两个不同下标,再看看两个字符串是否相等。
代码如下:

class Solution {
public:
    bool areAlmostEqual(string s1, string s2) {
        int n = s1.size();
        vector<int> a;
        for(int i = 0; i < n; ++i){
            if(s1[i] == s2[i]) continue;
            a.push_back(i);
        }
        if(a.size() == 0) return true;
        if(a.size() == 1 || a.size() > 2) return false;
        swap(s1[a[0]], s1[a[1]]);
        if(s1[a[0]] == s2[a[0]] && s1[a[1]] == s2[a[1]]) return true;
        return false; 
    }
};

第二题

(题号5702):nc题
在这里插入图片描述
在这里插入图片描述
这数据范围给的,太nc了出题人。
既然edges.length == n - 1
那么我只需要找出数组前两行相等的数就行

class Solution {
public:
    int findCenter(vector<vector<int>>& edges) {
        int a = edges[0][0], b = edges[0][1], c = edges[1][0], d = edges[1][1];
        if(a == c || a == d) return a;
        return b;
    }
};

第三题 (优先队列+自定义排序)

(编号5703 – 优先队列):
在这里插入图片描述
在这里插入图片描述
数据范围10^5:nlogn
优先队列
主要是卡在了如何给优先队列写自定义排序,找了好久博客
这里附上两种写法:

//写法一:
struct node{
    int u;
    long long dis;
    bool operator < (const node &x) const{
        return dis > x.dis;
    }
};
//写法二:
struct cmp1{
    bool operator () (比较数据类型 &a1, 比较数据类型 &a2){
        return 比较方法;
    }
}

思路:
优先队列排序:分子分母同时+1,增量最大的班级就加上一个同学,然后重新排序,直到加完所有同学

class Solution {
public:
    typedef struct _A{ //定义类型
    double a;
    double b;
}A;

struct cmp1{ //自定义比较
    bool operator ()(A &a1, A &a2){
        double t1 = (a1.a + 1) / (a1.b + 1) - a1.a / a1.b;
        double t2 = (a2.a + 1) / (a2.b + 1) - a2.a / a2.b;
        return t1 < t2; 
    }
};

	double maxAverageRatio(vector<vector<int>>& classes, int extraStudents) {
	    int n = classes.size();
	    priority_queue<A, vector<A>, cmp1> q1;
	    for(int i = 0; i < n; ++i){ //入队
	        A t;
	        t.a = classes[i][0], t.b = classes[i][1];
	        q1.push(t);
	    }
	    while(extraStudents != 0){ //加增量
	        A t = q1.top();
	        q1.pop();
	        t.a += 1, t.b += 1;
	        q1.push(t);
	        extraStudents--;
	    }
	    double cnt = 0;
	    while(!q1.empty()){ //出队统计
	        A t = q1.top();
	        q1.pop();
	        cnt += t.a / t.b;
	    }
	    return cnt / n;
	}
};

第四题 (双指针贪心)

(编号5704–双指针贪心):
在这里插入图片描述
在这里插入图片描述
数据范围 10^5 : n 或 nlogn
题解链接: 点这里.
(题解为本人所写)
思路 :
区间必须得包含下标k
那么可以从k开始向左向右寻找以 nums[k] 为最小值的好子数组:
1.nums[r] >= nums[k] : r++
2.nums[l] >= nums[k] : l–
直到左右边界都出现比nums[k]小的数,此时计算最大可能分数 res = (r - l - 1) * nums[k]
同时更新 nums[k] 为左右边界中的较大者,继续寻找以 nums[k] 为最小值的好子数组
直到 l < 0 && r == n

时间复杂度:O(n)
空间复杂度:O(1)

class Solution {
public:
    int maximumScore(vector<int>& nums, int k) {
        int l = k, r = k, n = nums.size(), res = 0; //定义左右边界l r,最大可能分数res
        while(1){ 
            while(r < n && nums[r] >= nums[k]) r++; //向右寻找以nums[k]为最小值的好子数组
            while(l >= 0 && nums[l] >= nums[k]) l--; //向左寻找以nums[k]为最小值的好子数组
            res = max(res, (r - l - 1) * nums[k]);  //更新最大可能分数
            if(l < 0 && r == n) break; //遍历完数组,直接退出循环
            if(l >= 0 && r < n) nums[k] = max(nums[l], nums[r]); //更新nums[k] 为左右边界中的较大者
            else if(l < 0) nums[k] = nums[r]; //左边遍历完了,更新nums[k]为右边界
            else nums[k] = nums[l]; //右边遍历完了,更新nums[k]为左边界
        }
        return res;
    }
};

一开始为什么错:
在这里插入图片描述
这里判断更新条件根本就没必要,当初不知道为什么脑子想抽了。
因为这里的l与r左右边界都是不算进好子数组的,所以无论l,r在不在数组范围,好子数组长度都是(r - l - 1)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值