本文正在参加「Python主题月」,详情查看 活动连接html
这是 LeetCode 上的 剑指 Offer 53 - I. 在排序数组中查找数字 I ,难度为 简单。git
Tag : 「二分」github
统计一个数字在排序数组中出现的次数。数组
示例 1:markdown
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
复制代码
示例 2:app
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
复制代码
限制:oop
一个朴素的想法是,找到目标值 「首次」出现或者「最后」出现的下标,而后「日后」或者「往前」进行数量统计。post
Java 代码:ui
// 找到目标值「最后」出现的分割点,并「往前」进行统计
class Solution {
public int search(int[] nums, int t) {
int n = nums.length;
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] <= t) l = mid;
else r = mid - 1;
}
int ans = 0;
while (r >= 0 && nums[r] == t && r-- >= 0) ans++;
return ans;
}
}
复制代码
// 找到目标值「首次」出现的分割点,并「日后」进行统计
class Solution {
public int search(int[] nums, int t) {
int n = nums.length;
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= t) r = mid;
else l = mid + 1;
}
int ans = 0;
while (l < n && nums[l] == t && l++ >= 0) ans++;
return ans;
}
}
复制代码
Python 3 代码:spa
class Solution:
# 找到目标值「最后」出现的分割点,并「往前」进行统计
def search(self, nums: List[int], t: int) -> int:
n = len(nums)
l, r = 0, n - 1
while l < r:
mid = l + r + 1 >> 1
if nums[mid] <= t:
l = mid
else:
r = mid - 1
ans = 0
while r >= 0 and nums[r] == t:
ans += 1
r -= 1
return ans
复制代码
class Solution:
# 找到目标值「首次」出现的分割点,并「日后」进行统计
def search(self, nums: List[int], t: int) -> int:
n = len(nums)
l, r = 0, n - 1
while l < r:
mid = l + r >> 1
if nums[mid] >= t:
r = mid
else:
l = mid + 1
ans = 0
while l < n and nums[l] == t:
ans += 1
l += 1
return ans
复制代码
进一步,咱们能够直接通过两次「二分」找到左右边界,计算总长度便是 的数量。
Java 代码:
class Solution {
public int search(int[] nums, int t) {
int n = nums.length;
if (n == 0) return 0;
int a = -1, b = -1;
// 二分出左边界
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= t) r = mid;
else l = mid + 1;
}
if (nums[r] != t) return 0;
a = r;
// 二分出右边界
l = 0; r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] <= t) l = mid;
else r = mid - 1;
}
if (nums[r] != t) return 0;
b = r;
return b - a + 1;
}
}
复制代码
Python 3 代码:
class Solution:
def search(self, nums: List[int], t: int) -> int:
n = len(nums)
if not n:
return 0
a = b = -1
# 二分出左边界
l, r = 0, n - 1
while l < r:
mid = l + r >> 1
if nums[mid] >= t:
r = mid
else:
l = mid + 1
if nums[r] != t:
return 0
a = r
# 二分出右边界
l, r = 0, n - 1
while l < r:
mid = l + r + 1 >> 1
if nums[mid] <= t:
l = mid
else:
r = mid - 1
if nums[r] != t:
return 0
b = r
return b - a + 1
复制代码
这是咱们「刷穿 LeetCode」系列文章的第 No.剑指 Offer 53 - I
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,咱们将先把全部不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路之外,还会尽量给出最为简洁的代码。若是涉及通解还会相应的代码模板。
为了方便各位同窗可以电脑上进行调试和提交代码,我创建了相关的仓库:github.com/SharingSour… 。
在仓库地址里,你能够看到系列文章的题解连接、系列文章的相应代码、LeetCode 原题连接和其余优选题解。