
二分查找
abant2
世界上最菜的arcem
展开
-
阿里笔试 填充型二分
牛牛上幼儿园,有5个数,每次选择4个数进行减一操作,牛牛没学过负数,所以减到0就停止了。 问最多可以减多少次,5个数范围:1e9此题贪心很难做,和力扣2141类似,有点像填充型二分,但还是区别挺大的。我们考虑最多能减x次。当然,由于每次需要减4个数,我们不可能真的去减,有些难以操作,我们可以考虑,每次有一个数不减。我们换个思路考虑,如果说要减x次,如果其中一个数大于等于x,那么每次减他都可以,如果有4个数以上大于等于x,那么x肯定是满足要求的。但如果有数 aaa 小于 xxx,那么他至少要被豁免 x−原创 2022-04-11 16:51:51 · 255 阅读 · 0 评论 -
leetcode 2141 填充型二分
此题还是挺难想的,首先做一个假设,假设n台电脑最多能运行x分钟,如果所有电池加起来能运行nx分钟,能不能满足要求?考虑第一种例外,即如果有电池电量大于x,那么它给x充满电后,也没有时间再给别的电脑充电了,所以如果有电池电量超过x,那么一定满足不了要求。所以我们应该做一下裁剪,让每个电池电量和x取最小值。那么我们接着考虑,裁剪后,如果所有电池加起来能运行nx分钟,能否满足要求?这个是可以满足的,证明也很简单,我们直接在每个电脑上累加电池,直到大于等于x。不管等于的,我们会得到一批大于x和小于x的电脑。我.原创 2022-04-11 15:25:03 · 494 阅读 · 0 评论 -
leetcode 69 求平方根
题目不用再说了,但一个要求是要返回整数,这就存在一个问题,就是输入为1的时候,永远不可能得到1,因为int是向下取整,所以对于1要特殊处理。class Solution {public: int mySqrt(int x) { if(x == 1)return 1; double l = 0, r = x; if(x < 1)r = 1; while(l<r) { double原创 2021-09-15 15:58:14 · 123 阅读 · 0 评论 -
leetcode 240 单调矩阵搜索
此题和类似单调矩阵不太一样,每个小于target的行都有可能是。思路一:与普通矩阵类似,对每个小于target的行做二分查找class Solution {public: int bisect(vector<int> &v, int target) { int l = 0, r = v.size()-1; while(l<r) { int mid = ceil((l+r)/2.0);.原创 2021-07-28 14:04:27 · 182 阅读 · 0 评论 -
leetcode 74 类似单调矩阵 二分搜索
此题的矩阵和单调矩阵很像,是肯定要用二分的题目,先第一次二分,找到合适的左区间,第二次找到精确数值,要注意mid的判断,是核心。class Solution {public: int bisect(vector<int> &v, int target) { int l = 0, r = v.size()-1; while(l<r) { int mid = ceil((l+r)/2.0);.原创 2021-07-26 23:33:00 · 105 阅读 · 0 评论 -
leetcode 33 81 旋转数组搜索元素问题 二分本质
33:无重复元素首先思考两个问题:能否轻易找到旋转点?能否判断目标数在哪个部分?其实这两点都是很好解决的,第一点需要之前的题,可以用二分法和最右边元素进行比较,找到起始点即可。之后,我们通过目标数和数组的第一个数比较,可知道他在哪一部分,之后在对应部分做一次二分即可。class Solution {public: int search(vector<int>& nums, int target) { // 找旋转点 int l =原创 2021-04-28 16:21:57 · 123 阅读 · 0 评论 -
求字典序最小的最长上升子序列
此题如背包问题一样,回溯是可以解决的,我们需要先得到以当前字符结尾的最大长度数组,即dp数组。我们可以用dp+二分方法,在得到单调栈数组的同时仍可以获得dp数组(这是一个技巧)之后便可以做回溯了,我们可以使用贪心的方式进行回溯。每次只需要找到最靠右的元素即可。因为若两个长度相同,靠前的一定比靠后的大,不然两个不可能相等,所以每次选靠后的就可以解决问题。class Solution {public: /** * retrun the longest increasing subsequ原创 2021-04-28 14:14:08 · 740 阅读 · 0 评论 -
leetcode 1802 线性变化问题 模拟+二分
解法一:模拟此题的模拟分为两个阶段。首先把地面铺满,这样一定是满足要求的,然后在index处开始累加即可。在第一阶段咱们直接模拟,index处的值每次加一,这个值减去2就是他每次辐射到的范围。当两边都被辐射到,即进入第二阶段后,可以直接用简单除法完成。class Solution {public: int maxValue(int n, int index, int maxSum) { int sum = n; int ret = 1; whil原创 2021-04-27 22:20:58 · 193 阅读 · 0 评论 -
leetcode 153, 154 旋转数组最小值问题
第一件要明确的事,咱们要找的元素肯定在右半部分,当然可能不存在左半部分。这样一来,我们希望在二分的时候,如果只有右半部分,也能求出最终解,这就需要我们必须和右端的元素进行比较。如果和左边比较,当我们完全进入右半部分时,指针根本处理不了这种情况。第二件事就是,当mid和r处元素相等时,要r–。这个基本可以当成结论来看了,由于无法判断,只能退化成O(N)。这是一种无奈的妥协。两个题代码分别如下:class Solution {public: int findMin(vector<int&g原创 2021-04-19 22:15:01 · 118 阅读 · 0 评论 -
leetcode 4 寻找两个正序数组的中位数 元素排除+二分分块 全三种做法
做法1:O(N+M)做法为一次排除一个元素,此做法为一次排除k个元素。我们的目标是找到中位数,计算其下标并记录在to_find变量中其中,k = int(to_find/2)通过比较两个数组第k个值的大小,可以一次删去k个元素,从而实现二分class Solution: def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float: # k: kth smallest numb原创 2020-10-14 17:03:33 · 174 阅读 · 1 评论 -
leetcode 222 二分完全二叉树
解法一:dfs暴力求解# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: def countNodes(self, root: TreeNode) -> int: self.原创 2020-11-24 14:08:25 · 126 阅读 · 0 评论 -
leetcode 34 二分查找
本来是个很简单的题,前几天看视频也遇到了,两次二分就行,可是就那么亿点细节愣是整了半天。首先是移位,在已知要左移或右移时,应先改变left或者right再动指针。然后就是判别条件,应该是left <= right,这样能进行最后一次操作,之后就会退出,因为移位时是必定要动一位的,所以这种状态只能持续一次,代码如下:from math import ceilclass Solution: def searchRange(self, nums: List[int], target: int)原创 2020-12-01 14:41:53 · 149 阅读 · 0 评论 -
leetcode 300 LIS 最长上升子序列 dp+贪心
首先是300,经典的最长上升子序列问题解法一:普通dp用dp做其实是很简单的,找到关键:对于每个元素,记录以这个元素为末尾的最长子序列长度。然后很容易就可想到递推公式,代码如下:class Solution: def lengthOfLIS(self, nums: List[int]) -> int: ret = 1 dp = [1 for _ in range(len(nums))] for i in range(1, len(nums)原创 2020-12-14 22:13:32 · 143 阅读 · 0 评论 -
leetcode 354 LIS变形
这种二维问题一般都是排序+dp,可以转化为LIS问题。解法一:dp状态转移方程为以当前数字结尾的最长序列长度。注意:此题不要用max,不然会超时。class Solution: def maxEnvelopes(self, envelopes: List[List[int]]) -> int: if not envelopes: return 0 arrs = sorted(envelopes, key=lambda x: (x[0], x[1]))原创 2021-03-04 13:35:57 · 144 阅读 · 1 评论 -
剑指offer 04 单调矩阵
本题中的矩阵,每行每列都是单调递增的,解法一:二分这道题很容易让人想到二分。二分如果要选左边的元素,那么需要用ceil函数来确定中间,这是一个坑。然后二分的思路就是确定候选区间,先根据第一个元素选出右区间,再根据最后一个元素选出左区间,在区间内二分即可。from math import ceilclass Solution: def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:原创 2021-03-05 15:20:42 · 444 阅读 · 0 评论 -
剑指offer 11 二分处理两个顺序数组 很经典
此题又是一道无敌的题目,其二分处理之难想令人发指。常规的二分如果想让左指针=mid+1,说明左指针偏右,要让mid值偏左,所以向下取整。此题如果大于右边,说明mid在左边部分,取mid+1. 所以要此题也要向下取整。关键是在等于时的处理,由于本题的特殊性,如果mid等于右边,无法判断向左还是向右。此时我们让右指针向左移动一位。现在要证明的是,这一次移动不会有危险。什么叫危险?就是右指针恰好指向我们要找的数。若发生这种情况,我们可以发现,mid仍然等于这个数,这个数仍在搜索区间。让我们思考一下,此时mid原创 2021-03-15 14:26:54 · 118 阅读 · 0 评论