每日算法刷题Day19 5.31:leetcode二分答案3道题,用时1h

6. 475.供暖器(中等,学习check函数双指针思想)

475. 供暖器 - 力扣(LeetCode)

思想

1.冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。在加热器的加热半径范围内的每个房屋都可以获得供暖。现在,给出位于一条水平线上的房屋 houses 和供暖器 heaters 的位置,请你找出并返回可以覆盖所有房屋的最小加热半径。

2.单调性检验:加热半径越小,越可能不能覆盖所有房屋,不满足条件,所以存在一个最小加热半径

3.难点在于check函数怎么写,我原来的思想是遍历heaters,然后把[heaters[i]-x,heaters[i]+x]变为true,但这样会超出内存限制

4.学习:

(1)先将houses和heaters进行排序(最重要)

(2)让i指向当前判断房屋houses[i],然后j指向可能(先确保右边界成立) 覆盖到的heaters[j],x为加热半径

  • 当且仅当heaters[j]+x<houses[i]时,第i个房屋必定不能被第j个加热器覆盖,然j自增
  • 退出循环说明找到合适的j(右边界必然成立,找到能覆盖的最小加热器),再判断heaters[j]-x<=houses[i]<=heaters[j]+x是否满足
代码

c++:

复制代码
class Solution {
public:
    bool check(vector<int>& houses, vector<int>& heaters, int mid) {
        int n = houses.size(), m = heaters.size();
        int j = 0;
        for (int i = 0; i < n; ++i) {
            while (j < m && houses[i] > heaters[j] + mid)
                ++j; // 寻找能覆盖的最小加热器
            if (j < m && heaters[j] - mid <= houses[i] &&
                houses[i] <= heaters[j] + mid)
                continue; // 满足条件看下一个房子
            return false; // 不满足条件
        }
        return true;
    }
    int findRadius(vector<int>& houses, vector<int>& heaters) {
        int res = 0;
        sort(houses.begin(), houses.end());
        sort(heaters.begin(), heaters.end());
        int maxho = INT_MIN, minho = INT_MAX, maxhe = INT_MIN, minhe = INT_MAX;
        for (const int x : houses) {
            maxho = max(maxho, x);
            minho = min(minho, x);
        }
        for (const int x : heaters) {
            maxhe = max(maxhe, x);
            minhe = min(minhe, x);
        }
        int left = 0, right = max(abs(maxho - minhe), abs(maxhe - minho));
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (check(houses, heaters, mid)) {
                res = mid;
                right = mid - 1;
            } else
                left = mid + 1;
        }
        return res;
    }
};
7. 2594.修车的最少时间(中等)

2594. 修车的最少时间 - 力扣(LeetCode)

思想

1.给你一个整数数组 ranks ,表示一些机械工的 能力值 。ranksi 是第 i 位机械工的能力值。能力值为 r 的机械工可以在 r * n2 分钟内修好 n 辆车。同时给你一个整数 cars ,表示总共需要修理的汽车数目。请你返回**修理所有汽车(条件) ** 最少 需要多少时间(答案)

2.类似于3296.移山所需的最少秒数

3.单调性检验,时间越少,越不可能修理所有汽车,所以存在一个最少时间

代码

c++:

复制代码
class Solution {
public:
    bool check(vector<int>& ranks, int cars, long long mid) {
        long long sum = 0;
        for (const int x : ranks) {
            sum += (long long)sqrt(mid / x);
            if (sum >= cars)
                return true;
        }
        return false;
    }
    long long repairCars(vector<int>& ranks, int cars) {
        long long res = 0;
        int minval = INT_MAX;
        for (const int x : ranks)
            minval = min(minval, x);
        long long left = 1, right = 1LL * minval * cars * cars;
        while (left <= right) {
            long long mid = left + ((right - left) >> 1);
            if (check(ranks, cars, mid)) {
                res = mid;
                right = mid - 1;
            } else
                left = mid + 1;
        }
        return res;
    }
};

1.不用转换为long long的,可以写成1LL

8. 1482.制作m束花所需的最少天数

1482. 制作 m 束花所需的最少天数 - 力扣(LeetCode)

思想

1.给你一个整数数组 bloomDay,以及两个整数 mk 。现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花(小条件) 。花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好可以用于 一束 花中。请你返回从花园中摘 m 束花(条件) 需要等待的最少的天数(答案) 。如果不能摘到 m 束花则返回 -1

2.单调性检验:天数越少,越不能摘到m束花,所以存在一个最少天数

代码

c++:

复制代码
class Solution {
public:
    bool check(vector<int>& bloomDay, int m, int k, int mid) {
        int n = bloomDay.size();
        int sum = 0, cnt = 0;
        for (int i = 0; i < n; ++i) {
            if (bloomDay[i] <= mid) {
                ++cnt;
                if (cnt == k) {
                    ++sum;
                    if (sum >= m)
                        return true;
                    cnt = 0;
                }
            } else {
                cnt = 0;
            }
        }
        return false;
    }
    int minDays(vector<int>& bloomDay, int m, int k) {
        int res = -1;
        int maxval = INT_MIN;
        for (const int x : bloomDay)
            maxval = max(maxval, x);
        int left = 1, right = maxval;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (check(bloomDay, m, k, mid)) {
                res = mid;
                right = mid - 1;
            } else
                left = mid + 1;
        }
        return res;
    }
};
相关推荐
珂朵莉MM11 分钟前
2022 RoboCom 世界机器人开发者大赛(睿抗 caip) -高职组(国赛)解题报告 | 科学家
java·人工智能·python·算法·职场和发展·机器人
STY_fish_20122 小时前
手拆STL
java·c++·算法
小纭在努力2 小时前
【算法设计与分析】实验——改写二分搜索算法,众数问题(算法分析:主要算法思路),有重复元素的排列问题,整数因子分解问题(算法实现:过程,分析,小结)
数据结构·python·学习·算法·算法设计与分析·实验报告·实验
芜湖xin3 小时前
【题解-洛谷】B4278 [蓝桥杯青少年组国赛 2023] 简单算术题
算法·
理智的灰太狼3 小时前
题目 3298: 蓝桥杯2024年第十五届决赛真题-兔子集结
算法·职场和发展·蓝桥杯
阳洞洞6 小时前
79. Word Search
leetcode·回溯
kingmax542120086 小时前
【洛谷P9303题解】AC- [CCC 2023 J5] CCC Word Hunt
数据结构·c++·算法·广度优先
白熊1887 小时前
【机器学习基础】机器学习入门核心算法:XGBoost 和 LightGBM
人工智能·算法·机器学习
bai_lan_ya7 小时前
数据结构-排序-排序的七种算法(2)
数据结构·算法·排序算法
全域智图9 小时前
元胞自动机(Cellular Automata, CA)
人工智能·算法·机器学习