Leetcode刷题(Week6)—— 二分与单调队列/栈专题

刷题时间: 2019/04/15 – 2019/04/19
主播:yxc(闫雪灿)
视频链接: https://www.bilibili.com/video/av35162983

题号题目链接
4Median of Two Sorted Arrayshttps://leetcode.com/problems/median-of-two-sorted-arrays/submissions/
81Search in Rotated Sorted Array IIhttps://leetcode.com/problems/search-in-rotated-sorted-array-ii/
69Sqrt(x)https://leetcode.com/problems/sqrtx/
33Search in Rotated Sorted Arrayhttps://leetcode.com/problems/search-in-rotated-sorted-array/
34Find First and Last Position of Element in Sorted Arrayhttps://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
74Search a 2D Matrixhttps://leetcode.com/problems/search-a-2d-matrix/
153Find Minimum in Rotated Sorted Arrayhttps://leetcode.com/problems/find-minimum-in-rotated-sorted-array/
162Find Peak Elementhttps://leetcode.com/problems/find-peak-element/
155Min Stackhttps://leetcode.com/problems/min-stack/
496Next Greater Element Ihttps://leetcode.com/problems/next-greater-element-i/
42Trapping Rain Waterhttps://leetcode.com/problems/trapping-rain-water/
84Largest Rectangle in Histogramhttps://leetcode.com/problems/largest-rectangle-in-histogram/
85Maximal Rectanglehttps://leetcode.com/problems/maximal-rectangle/
475Heatershttps://leetcode.com/problems/heaters/
239Sliding Window Maximumhttps://leetcode.com/problems/sliding-window-maximum/
456132 Patternhttps://leetcode.com/problems/132-pattern/
739Daily Temperatureshttps://leetcode.com/problems/daily-temperatures/

在这里插入图片描述

解题心得

No.4 求两个排序数组的中位数 (AC)

  • 本题要求用小于O(log(m +n))的时间复杂度来完成,想到用二分
  • 假设两个数组的长度分别为l1, l2, 那么总长度为 l = l1 + l2, 我们需要找到前 (l +1) / 2 个数。为了方便,我们保证第一个数组的长度l1 小于 第二个数组的长度l2。 我们需要做的是二分第一个数组l1, 得到第一个数组属于前(l + 1)/ 2 的元素个数后,确定第二个数组中属于前(l + 1)/ 2 的元素,使得划分满足 l1[len_1 - 1] < l2[len_2] && l1[len_1] > l2[len_2 - 1]。 这样就可以直接根据当前划分去求中位数。若l为奇数,则直接返回max(l1[len_1 - 1], l2[len_2 - 1]);若l为偶数, 则返回 max(l1[len_1 - 1], l2[len_2 - 1]) + min(l1[len_1], l2[len_2 ]) >> 1。 当前这里考虑的是一般情况,若len_1, len_2是在边界,还需要特殊处理。

No. 81 在升序的折叠(循环)数组中查找一个数 (AC)(划重点)

  • 本题需要特殊处理接种特殊情况: 1. 没有折叠,即仍上升序列; 2. 结尾和第一个元素相同的元素需要删掉。
  • 特判这两种情况后,先二分第一个比首个元素小的元素,即折叠点
  • 然后判断target 和 第一个元素的大小,确定答案在折叠点的左半部分还是右半部分。然后二分得到最终的答案。

No.69 求一个数开根号的值,向下取整。(AC)

  • 二分问题。
  • 在本问题中,target * 1ll * target <= x, 即最小值最大是…的问题,可以根据不等式确定判断函数中的符号,确定是第二种模板。
  • 二分经典模板 https://www.acwing.com/blog/content/31/
版本1
当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
C++ 代码模板:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}

版本2
当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。
C++ 代码模板:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

以上代码中,
版本1(mid = l + r >> 1)对应:最大值最小是…的问题
版本2 (mid = l + r + 1 >> 1) 对应: 最小值最大是…的问题

No.33 在旋转树中中查找一个数 (AC)

  • 首先二分查找旋转点,check函数中比较的对象是nums[0]
  • 然后根据nums[0]和tatget的值的关系,确定答案在左半部分还是右半部分,仍然用二分。这里需要注意的是,需要判断答案是否存在数列中。
  • 还有一个边界一定要考虑!即元素组没有旋转,此时直接在元素中查询即可

No.34 Find First and Last Position of Element in Sorted Array (AC)

  • 二分问题
  • 分别二分出一个数字第一次和最后一次出现的位置,判断套件中的符号按照上一题的总结来写。
  • 找出现的第一个位置时, 是nusm[i] >= target,由此确定判断条件;找最后一个位置时,是nums[i] <= target,由此确定判断条件。

No.74 Search a 2D Matrix (AC)

  • 从左下角活右上角开始遍历,每次删掉一行或一列。O(m + n)
  • 二分来做。因为二维展成一维之后是严格递增的。
  • 需要注意的是,一维坐标转换成二维坐标时除的是列的值

No.153 Find Minimum in Rotated Sorted Array (AC)

  • 二分来做。
  • 二分条件是target < nums[0],这也是我们要找的数需要满足的条件。这里不能取等号,可以多测试几个样例。
  • 没有旋转的数组(整体呈现升序)边界条件要特判,不符合我们的二分条件。

No.162 Find Peak Element (AC)

  • 线性做法,从前往后扫描,两边边界特判
  • 二分来做。需要分析清楚的是,若nums[mid] < nums[mid + 1],则右边一定存在峰值,否则左边一定存在峰值。

No.155 Min Stack(AC)

  • 用一个辅助栈存储栈内每个元素的最小值
  • 需要判辅助栈为空的边界条件

No.496 Next Greater Element I (AC)

  • 用单调栈来做。
  • 维护一个单调递增的栈,从后往前开始扫描
  • 栈为空的情况需要特判

No.42 Trapping Rain Water (AC)

  • 分别计算每一个柱子可装的水是多少,这个值由该柱子左右两边最高的柱子中相对矮的一根柱子决定,即w[i] = min(left_max[i], right_max[i]) - height[i],若w[i]的值小于0, 则取0;
  • 分别从前后扫描两遍,得到左边和右边的最大值。
  • 再遍历一遍统计结果。
  • 也可以用单调栈进一步优化,参考 https://www.acwing.com/solution/LeetCode/content/121/

No.84 Largest Rectangle in Histogram (AC)

  • 单调栈来做
  • 长方体的最大面积由它可延伸的面积决定,即要找到一根柱子它的左边和右边第一个比它矮的柱子的索引。
  • 前后遍历两次,维护两个单调栈

No.85 找01矩阵中由1构成的最大矩阵的面积 (AC)

  • 和上一题#84相似
  • 先求出矩阵中各个点的高,然后求出以此高为中心,能扩展的最大宽度,即找到它的两遍第一个比他小的元素的位置,然后求矩形面积,并不断更新。
  • 对于矩阵中的每一行,分别用单调栈从前往后和从后往前求它左右第一个比它小的元素所在的索引,然后求面积。
  • 总共需要把矩阵遍历4遍,时间复杂度为O(mn)。

No.475 Heaters (WA–>AC)

  • 二分找到每个房屋到暖气的最近距离,然后输出所有距离的最大值
  • 为了避免比houses当前索引更大/小的值在heaters中找不着,一开始在heaters数组中插入一个INT_MIN, INT_MAX,然后对heaters数组排序
  • 一开始的思路:求两个暖气片之间的最大距离,然后一头一尾的暖气片特殊处理,这里会存在的问题是,当有若干个暖气片远大于房屋的最大索引时,就会出问题。这个方法容易写出bug,不是一个很好的方法。

No.239 Sliding Window Maximum (AC)

  • 本题需要维护一个双向队列deque,选择数据结构时要想清楚。
  • 当对头元素失效,删除dq.pop_front();若当前元素大于对位元素,则循环删除对位元素dq.pop_back()
  • 只有当前遍历元素的索引大与等于滑动窗口的长度K时才开始记录答案。

queue和deque数据结构比较及相关操作

queue数据结构
特点: 先进先出,只能从队尾添加元素,队头删除元素
queue<int> q; // 创建
q.empty(); // 判空
q.size(); // 队列大小
q.push(s); // 从队尾新增元素
q.pop(); // 从队头删除元素
q.front(); // 返回队头元素的值
q.back(); // 返回队尾元素的值

deque数据结构
特点: 双端队列,可以在队头和队尾分别进行插入和删除操作
deque<int> dq; // 创建
dq.empty(); // 判空
dq.size(); // 队列大小 
dq.clear(); // 清空双端队列
dq.push_back(s); // 从队尾新增元素
dq.push_front(s); // 从队头新增元素
dq.back(); // 返回队尾元素
dq.front(); // 返回队头元素
dq.pop_back(); // 删除队尾元素
dq.pop_front(); // 删除队头元素

No.456 132 Pattern (AC)

  • 单调栈来做
  • 从后往前枚举,维护一个单调递增栈。
  • 需要记录ak的最大值。因为ai< ak < aj (i < j < k),所以在枚举过程中,ak一定会被弹出栈,因此ak的最大值是弹出栈的元素中的最大值。
  • 若当前枚举元素小于ak,则满足132模式的子序列已找到。
  • 若从前往后枚举,则ak是否入栈不好判断。

No.739 计算几天后会比当前温度高 (AC)

  • 从后往前遍历,维护一个单调递增的栈
  • 注意边界为空条件的判断即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值