LeetCode学习-第二十天

50 篇文章 0 订阅
28 篇文章 0 订阅

第二十天

我使用的C++,错误的地方请见谅,文章初衷仅用来督促本人学习,如果恰巧能够给你带来帮助,我会十分开心。

一、239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sliding-window-maximum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

可以对每一个滑动窗口 进行遍历,简单试验一下发现有n - k + 1个滑动窗口,那么对于整个遍历就有O((n - k + 1)k)的时间复杂度,这对于困难题来说是不允许的,所以这里采用大根堆的数据结构来跟新最大值

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        priority_queue<pair<int, int>> q;
        int n = nums.size();
        for (int i = 0; i < k; ++i){//将前k个元素排入堆中
            q.emplace(nums[i], i);
        }
        vector<int> ans = {q.top().first};
        for (int j = k; j < n; ++j){
            q.emplace(nums[j], j);
            while(q.top().second <= j - k){
                q.pop();
            }
            ans.push_back(q.top().first);
        }
        return ans;
    }
};

二、5971. 打折购买糖果的最小开销

一家商店正在打折销售糖果。每购买 两个 糖果,商店会 免费 送一个糖果。

免费送的糖果唯一的限制是:它的价格需要小于等于购买的两个糖果价格的 较小值 。

比方说,总共有 4 个糖果,价格分别为 1 ,2 ,3 和 4 ,一位顾客买了价格为 2 和 3 的糖果,那么他可以免费获得价格为 1 的糖果,但不能获得价格为 4 的糖果。
给你一个下标从 0 开始的整数数组 cost ,其中 cost[i] 表示第 i 个糖果的价格,请你返回获得 所有 糖果的 最小 总开销。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-cost-of-buying-candies-with-discount
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    int minimumCost(vector<int>& cost) {
        sort(cost.begin(), cost.end());//升序排列
        int count = 0, sum = 0, n = cost.size();
        for (int i = n - 1; i >= 0; --i){
            if (count < 2){
                sum += cost[i];
                ++count;
            }
            else if (count == 2){
                count = 0;
                
            }
        }
        return sum;
        
    }
};

三、5972. 统计隐藏数组数目

给你一个下标从 0 开始且长度为 n 的整数数组 differences ,它表示一个长度为 n + 1 的 隐藏 数组 相邻 元素之间的 差值 。更正式的表述为:我们将隐藏数组记作 hidden ,那么 differences[i] = hidden[i + 1] - hidden[i] 。

同时给你两个整数 lower 和 upper ,它们表示隐藏数组中所有数字的值都在 闭 区间 [lower, upper] 之间。

比方说,differences = [1, -3, 4] ,lower = 1 ,upper = 6 ,那么隐藏数组是一个长度为 4 且所有值都在 1 和 6 (包含两者)之间的数组。
[3, 4, 1, 5] 和 [4, 5, 2, 6] 都是符合要求的隐藏数组。
[5, 6, 3, 7] 不符合要求,因为它包含大于 6 的元素。
[1, 2, 3, 4] 不符合要求,因为相邻元素的差值不符合给定数据。
请你返回 符合 要求的隐藏数组的数目。如果没有符合要求的隐藏数组,请返回 0 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-the-hidden-sequences
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    int numberOfArrays(vector<int>& differences, int lower, int upper) {
        long long mn = 0, mx = 0, now = 0;
        for (int x : differences) {
            now += x;
            mn = min(mn, now);//以0为基准的最大值与最小值差值范围
            mx = max(mx, now);
        }
        if (mx - mn > upper - lower) return 0;//这个范围自然不能大于给定范围
        return (upper - lower) - (mx - mn) + 1;//给定范围减去可能范围加一就是可能范围的数量
    }
};

还是数学功底的问题

四、34. 在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        //升序的话,相同元素都是排在一起的,直接遍历的话是n的时间复杂度,
        int n = nums.size();
        int first = 0, second = n - 1;
        while (first <= second){
            if (nums[first] != target){
                ++first;
            }
            if (nums[second] != target){
                --second;
            }
            else if (nums[first] == target && nums[second] == target){
                return vector<int>{first, second};
            }
            
        }
        
        return vector<int>{-1, -1};


    }
};
class Solution {
public:
    int BinarySearch(vector<int> & nums, int t, bool lower){
        int l = 0, r = nums.size() - 1, ans = nums.size();

        while (l <= r){
            int mid = (l + r) / 2;
            if ((nums[mid] >= t && lower) || nums[mid] > t){
                r = mid - 1;
                ans = mid;
            }
            else {
                l = mid + 1;
            }
        }
        return ans;
    }
    vector<int> searchRange(vector<int>& nums, int target) {
        //升序的话,相同元素都是排在一起的,直接遍历的话是n的时间复杂度,采用二分查找,分别找到左右两个坐标
        int left = BinarySearch(nums, target, true);//lower代表着是否查找坐下标
        int right = BinarySearch(nums, target, false) - 1;
        if (nums[left] == target && nums[right] == targrt){
            return vector<int> {left, second};
        }
        else {
            return vector<int> {-1, -1};
        }    
        


    }
};

五、33. 搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //之前的二分查找都是在有序序列中进行,这里虽然是部分有序,也可以进行,关键是要判断target在哪部分的升序序列中
        //可以发现,将数组一分为二后,一定可以得到一个有序序列,一个无序序列,
        int n = nums.size();
        if (!n){
            return -1;

        }
        if (n == 1){
            return target == nums[0] ? 0 : -1;

        }
        int l = 0, r = n - 1;
        while (l <= r){
            int mid = (l + r) / 2;
            if (nums[mid] == target){
                return mid;
            }
            if (nums[0] <= nums[mid]){//0-mid位有序部分
                if (nums[0] <= target && target <= nums[mid]){//并且target在当前序列部分
                    r = mid - 1;

                }
                else {
                    l = mid + 1;
                }
            }
            else {//0-mid为非有序部分
                if (nums[mid] <= target && target <= nums[n - 1]){//target在有序部分
                    l = mid + 1;

                }
                else {
                    r = mid - 1;
                }

            }
        }
        return -1;



    }
};

重点是二分查找的边界变化只能在有序序列中变化;

六、74. 搜索二维矩阵

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-a-2d-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    bool searchMatrix(vector<vector<int>> matrix, int target) {
        auto row = upper_bound(matrix.begin(), matrix.end(), target, [](const int b, const vector<int> &a) {//找到列
            return b < a[0];
        });
        if (row == matrix.begin()) {
            return false;
        }
        --row;
        return binary_search(row->begin(), row->end(), target);
    }
};

呃呃呃,题解方法看懂了,代码没看懂

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值