LeetCode第23场双周赛

总结:四道题难度都不大,只要细心,就可以全部做出来。

5360. 统计最大组的数目

题目:

    给你一个整数 n 。请你先求出从 1 到 n 的每个整数 10 进制表示下的数位和(每一位上的数字相加),然后把数位和相等的数字放到同一个组中。

    请你统计每个组中的数字数目,并返回数字数目并列最多的组有多少个。1 <= n <= 10^4

输入:n = 13
输出:4
解释:总共有 9 个组,将 1 到 13 按数位求和后这些组分别是:
[1,10],[2,11],[3,12],[4,13],[5],[6],[7],[8],[9]。总共有 4 个组拥有的数字并列最多。

思考:发现是求每个数字的数位和,比如数字13,那么他的数位和就是4,应该和数字4、22、31、40一组,那么应该怎么保存每个数位和的个数呢,还要求最多的有多少组,仔细观察发现数字n最大为1e4,那么最大的数字就是9999,数位和是36。这个时候结果就显而易见,将开一个计数数组,保存每个数位和的个数,应为范围比较小,因此开一个数组大小为40,来计数,求每一个数字的数位和,,最后排序,取最大的数然后得到多的个数。代码如下:

class Solution {
public:
    int countLargestGroup(int n) {
        int a[50] = {0};
        for(int i = 1; i <= n; i++){
            int x = 0 , tmp = i;
            while(tmp){
                x += tmp % 10;
                tmp /= 10;
            }
            a[x]++;
            maxn = max(maxn, a[x]);
        }
        sort(a, a + 50);
        int maxn = 0, num = 0;
        for(int i = 0; i < 50; i++){
            num += (maxn == a[i] ? 1 : 0);
        }
        return num;
    }
};

5362. 构造 K 个回文字符串

题目:

  给你一个字符串 s 和一个整数 k 。请你用 s 字符串中 所有字符 构造 k 个非空 回文串 。

  如果你可以用 s 中所有字符构造 k 个回文字符串,那么请你返回 True ,否则返回 False 。

  • 1 <= s.length <= 10^5
  • s 中所有字符都是小写英文字母。
  • 1 <= k <= 10^5
输入:s = "annabelle", k = 2
输出:true
解释:可以用 s 中所有字符构造 2 个回文字符串。
一些可行的构造方案包括:"anna" + "elble","anbna" + "elle","anellena" + "b"啊

思考:仔细思考题意,要求构造k个非空字符串,那么首先如果s字符串的个数少于k,就直接不成立,然后思考怎么才能构造出k个非空字符串呢,尝试着写了几个字符串之后,发现构造字符串,偶数个的很好构造,唯一不能肯定的就是奇数个的情况,应为奇数个的字符数要是比较多,那么就不能得到结果,因此就可以发现问题所在,我们需要计算出26个字母中奇数个数的字符数,然后将奇数个数的自付出与k作比较,如果比k少,那么我就可以得到答案,不能就是false,代码也就很容易实现了。

class Solution {
public:
    bool canConstruct(string s, int k) {
        int l = s.size(), a[30] = {0}, num = 0;
        if(l < k)
            return false;
        for(int i = 0; i < l; i++){
            a[s[i] - 'a']++;
        }
        for(int i = 0 ;i < 27; i++){
            if(a[i] % 2 == 1)
                num ++;
        }
        if(num > k)
            return false;
        return true;
    }
};

5361. 圆和矩形是否有重叠

题目:

给你一个以 (radiusx_centery_center) 表示的圆和一个与坐标轴平行的矩形 (x1y1x2y2),其中 (x1y1) 是矩形左下角的坐标,(x2y2) 是右上角的坐标。

如果圆和矩形有重叠的部分,请你返回 True ,否则返回 False 。

换句话说,请你检测是否 存在 点 (xi, yi) ,它既在圆上也在矩形上(两者都包括点落在边界上的情况)。

输入:radius = 1, x_center = 0, y_center = 0, x1 = 1, y1 = -1, x2 = 3, y2 = 1
输出:true
解释:圆和矩形有公共点 (1,0) 
  • 1 <= radius <= 2000
  • -10^4 <= x_center, y_center, x1, y1, x2, y2 <= 10^4
  • x1 < x2
  • y1 < y2

思考:此题有一点点复杂,但代码很少,题目中要求判断是否圆与矩形相交,那么我们需要考虑的是什么情况下才会相交呢,只有三种情况,圆在矩形内、矩形在圆内和圆与矩形的边有交点,前面两个都是简单的方法,只需要判断圆心的位置和矩形的四个点的位置。

    有一点麻烦的是第三中情况,圆与矩形的边相交,但其实想要实现也很简单,只需要将矩形的一个点的横坐标x1带到园中,得到圆在横坐标为x1下的两个纵坐标,将圆的纵坐标和矩形的纵坐标作比较,看是否在其中,那么久可以得到结果了,代码也是不复杂,就有点多,我这里写的很丑,将就看一下。

class Solution {
public:
    bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
        radius = radius * radius;
        if(x1 > x2)
            swap(x1, x2);
        if(y1 > y2)
            swap(y1, y2);
        if(x_center >= x1 && x_center <= x2 && y_center >= y1 && y_center <= y2)
            return true;
        if((x_center - x1) * (x_center - x1) + (y_center - y1) * (y_center - y1) <= radius)
            return true;
        //判断四条边的交点
        double hy = 0;
        hy = sqrt(radius * 1.0 - (x1 - x_center) * (x1 - x_center) * 1.0);
        if(y_center * 1.0 + hy >= y1 && y_center * 1.0 + hy <= y2 || y_center * 1.0  -hy >= y1 && y_center * 1.0-hy <= y2)
            return true;
        hy = sqrt(radius * 1.0 - (x2 - x_center) * (x2 - x_center) * 1.0);
        if(y_center * 1.0 + hy >= y1 && y_center * 1.0 +  hy <= y2 || y_center * 1.0  -hy >= y1 && y_center * 1.0-hy <= y2)
            return true;
        hy = sqrt(radius * 1.0 - (y1 - y_center) * (y1 - y_center) * 1.0);
        if(x_center * 1.0 + hy >= x1 && x_center * 1.0 +  hy <= x2 || x_center * 1.0  -hy >= x1 && x_center * 1.0-hy <= x2)
            return true;
        hy = sqrt(radius * 1.0 - (y2 - y_center) * (y2 - y_center) * 1.0);
        if(x_center * 1.0 + hy >= x1 && x_center * 1.0 +  hy <= x2 || x_center * 1.0  -hy >= x1 && x_center * 1.0-hy <= x2)
            return true;
        return false;
    }
};

5363. 做菜顺序

题目:

https://leetcode-cn.com/problems/reducing-dishes/

一个厨师收集了他 n 道菜的满意程度 satisfaction ,这个厨师做出每道菜的时间都是 1 单位时间。

一道菜的 「喜爱时间」系数定义为烹饪这道菜以及之前每道菜所花费的时间乘以这道菜的满意程度,也就是 time[i]*satisfaction[i] 。

请你返回做完所有菜 「喜爱时间」总和的最大值为多少。

你可以按 任意 顺序安排做菜的顺序,你也可以选择放弃做某些菜来获得更大的总和。

输入:satisfaction = [-1,-8,0,5,-9]
输出:14
解释:去掉第二道和最后一道菜,最大的喜爱时间系数和为 (-1*1 + 0*2 + 5*3 = 14) 。每道菜都需要花费 1 单位时间完成。

  • n == satisfaction.length
  • 1 <= n <= 500
  • -10^3 <= satisfaction[i] <= 10^3

思考:简单贪心,首先是按照菜的满意度排序,有小到大,然后就可以从后向前判断是否需要做菜,需要考虑的是到这个菜的时候需不需要做,关键的点在于,如果选择做那么后面的满意度需要再加一次,那么问题来了,如果我当前菜的满意度很低,比后面再加一次的满意度还要低,我还需要继续做吗,很明显不需要,因为到此,如果我继续做的话,我总的满意度会减少,当前的满意度会是负数。所以贪心的核心就是需要将当前的满意度与满意度的前缀和做一个比较,如果两者之和小于0,那么就不适合继续下去,代码也就很容易实现了。

class Solution {
public:
    int maxSatisfaction(vector<int>& satisfaction) {
        sort(satisfaction.begin(), satisfaction.end());
        int l = satisfaction.size(); 
        int id = l, sum = 0, ii = 1,sum = 0;
        for(int i = l - 1;i >= 0; i--){
            if (satisfaction[i] == 0){
                id = i;
                continue;
            }            
            else if(satisfaction[i] + sum > 0){
                id = i;
                sum += satisfaction[i];
            }
            else
                break;
        }
        for(int i = id; i < l; i++){
            sum += satisfaction[i] * ii;
            ii++;
        }
        return sum;
    }
};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值