【Leetcode Sheet】Weekly Practice 12

Leetcode Test

2652 倍数求和(10.17)

给你一个正整数 n ,请你计算在 [1,n] 范围内能被 357 整除的所有整数之和。

返回一个整数,用于表示给定范围内所有满足约束条件的数字之和。

提示:

  • 1 <= n <= 103

【等差数列 + 容斥定理】

int sum(int n,int m){
    int k=n/m;
    return k * (k+1)/2 * m;
}
//等差数列求和
int sumOfMultiples(int n){
    return sum(n,3)+sum(n,5)+sum(n,7)-sum(n,15)-sum(n,21)-sum(n,35)+sum(n,105);
}

2530 执行K次操作后的最大分数(10.18)

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。你的 起始分数0

在一步 操作 中:

  1. 选出一个满足 0 <= i < nums.length 的下标 i
  2. 将你的 分数 增加 nums[i] ,并且
  3. nums[i] 替换为 ceil(nums[i] / 3)

返回在 恰好 执行 k 次操作后,你可能获得的最大分数。

向上取整函数 ceil(val) 的结果是大于或等于 val 的最小整数。

提示:

  • 1 <= nums.length, k <= 105
  • 1 <= nums[i] <= 109

【贪心 + 优先队列】

class Solution {
public:
    long long maxKelements(vector<int> &nums, int k) {
        priority_queue<int> pq(less<int>(), move(nums));
        //优先队列
        
        long long ans = 0;
        while (k--) {
            int x = pq.top();
            pq.pop();
            ans += x;
            pq.push((x + 2) / 3);
        }
        return ans;
    }
};

1726 同积元组(10.19)

给你一个由 不同 正整数组成的数组 nums ,请你返回满足 a * b = c * d 的元组 (a, b, c, d) 的数量。其中 abcd 都是 nums 中的元素,且 a != b != c != d

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 104
  • nums 中的所有元素 互不相同

【组合数学 + hash】

class Solution {
public:
    int tupleSameProduct(vector<int>& nums) {
        int n=nums.size();
        int ans=0;
        unordered_map<int,int> cnt;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                cnt[nums[i]*nums[j]]++;
            }
        }

        //C cnt ^ 2,排列组合
        for(auto &[k,v] : cnt){
            ans += v*(v-1)*4;
        }

        return ans;
    }
};

2525 根据规则将箱子分类(10.20)

给你四个整数 lengthwidthheightmass ,分别表示一个箱子的三个维度和质量,请你返回一个表示箱子 类别 的字符串。

  • 如果满足以下条件,那么箱子是

    "Bulky"
    

    的:

    • 箱子 至少有一个 维度大于等于 104
    • 或者箱子的 体积 大于等于 109
  • 如果箱子的质量大于等于 100 ,那么箱子是 "Heavy" 的。

  • 如果箱子同时是 "Bulky""Heavy" ,那么返回类别为 "Both"

  • 如果箱子既不是 "Bulky" ,也不是 "Heavy" ,那么返回类别为 "Neither"

  • 如果箱子是 "Bulky" 但不是 "Heavy" ,那么返回类别为 "Bulky"

  • 如果箱子是 "Heavy" 但不是 "Bulky" ,那么返回类别为 "Heavy"

注意,箱子的体积等于箱子的长度、宽度和高度的乘积。

提示:

  • 1 <= length, width, height <= 105
  • 1 <= mass <= 103

【模拟】注意体积的long long转换即可

char * categorizeBox(int length, int width, int height, int mass){
    bool bulky=0,heavy=0;
    if(length>=10000 || width>=10000 || height>=10000){
        bulky=1;
    }

    long long volumn=(long long)length*width*height;
    //可能会溢出emmm
    if(volumn>=1e9){
        bulky=1;
    }

    if(mass>=100){
        heavy=1;
    }

    if(bulky==1 && heavy==1){
        return "Both";
    }
    else if(bulky==0 && heavy==0){
        return "Neither";
    }
    else if(bulky==1 && heavy==0){
        return "Bulky";
    }
    else{
        return "Heavy";
    }
}

2316 统计无向图中无法互相到达点对数(10.21)

给你一个整数 n ,表示一张 无向图 中有 n 个节点,编号为 0n - 1 。同时给你一个二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 aibi 之间有一条 无向 边。

请你返回 无法互相到达 的不同 点对数目

提示:

  • 1 <= n <= 105
  • 0 <= edges.length <= 2 * 105
  • edges[i].length == 2
  • 0 <= ai, bi < n
  • ai != bi
  • 不会有重复边。

【DFS】

class Solution {
public:
    long long countPairs(int n, vector<vector<int>>& edges) {
        vector<vector<int>> g(n);
        for(auto &e: edges){
            int x=e[0],y=e[1];
            g[x].push_back(y);
            g[y].push_back(x);
        }
        //建图

        vector<int> vis(n);
        function <int(int)> dfs=[&](int x)->int{
            vis[x]=true;
            //标记当前已经访问过x点
            int size=1;
            for(int y: g[x]){
                if(!vis[y]){
                    size+=dfs(y);
                }
            }
            return size;
        };
        //DFS求出每个连通块的大小。

        long long ans=0;
        for(int i=0,total=0;i<n;i++){
            if(!vis[i]){
                //如果没访问过i点
                int size=dfs(i);
                ans+=(long)size*total;
                total+=size;
            }
        }
        return ans;
    }
};

1402 做菜顺序(10.22)

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

一道菜的 「 like-time 系数 」定义为烹饪这道菜结束的时间(包含之前每道菜所花费的时间)乘以这道菜的满意程度,也就是 time[i]*satisfaction[i]

返回厨师在准备了一定数量的菜肴后可以获得的最大 like-time 系数 总和。

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

提示:

  • n == satisfaction.length
  • 1 <= n <= 500
  • -1000 <= satisfaction[i] <= 1000

【贪心】

int cmp(void *a,void *b){
    return *(int*)a-*(int*)b;
}

int maxSatisfaction(int* satisfaction, int satisfactionSize){
    int n=satisfactionSize;
    qsort(satisfaction,n,sizeof(int),cmp);

    int f=0,s=0;
    //f是函数f(k),s是前缀和
    for(int i=n-1;i>=0;i--){
        s+=satisfaction[i];
        if(s<=0){
            //后面找不到更大的f(k)
            break;
        }
        f+=s;
        //f(k) = f(k-1) + s
    }
    return f;
}

2678 老人的数目(10.23)

给你一个下标从 0 开始的字符串 detailsdetails 中每个元素都是一位乘客的信息,信息用长度为 15 的字符串表示,表示方式如下:

  • 前十个字符是乘客的手机号码。
  • 接下来的一个字符是乘客的性别。
  • 接下来两个字符是乘客的年龄。
  • 最后两个字符是乘客的座位号。

请你返回乘客中年龄 严格大于 60 岁 的人数。

提示:

  • 1 <= details.length <= 100
  • details[i].length == 15
  • details[i] 中的数字只包含 '0''9'
  • details[i][10]'M''F' 或者 'O' 之一。
  • 所有乘客的手机号码和座位号互不相同。

【模拟】

int countSeniors(char ** details, int detailsSize){
    //0-9 dial number
    //10 sex
    //11-12 age
    //13-14 seat
    int cnt=0;//count for age >=61
    for(int i=0;i<detailsSize;i++){
        if(details[i][11]>'6'){
            cnt++;
        }
        else if(details[i][11]=='6'){
            if(details[i][12]>'0'){
                cnt++;
            }
        }
    }
    return cnt;
}

你可能感兴趣的:(Leetcode,Series,leetcode,算法,数据结构)