给定一个排序数组和一个目标值,找到第一个严格小于给定元素的元素。
例子:
Input : arr[] = {1, 2, 3, 5, 8, 12}
Target = 5
Output : 2 (Index of 3)
Input : {1, 2, 3, 5, 8, 12}
Target = 8
Output : 3 (Index of 5)
Input : {1, 2, 3, 5, 8, 12}
Target = 15
Output : -1
一个简单的解决方案是线性遍历给定数组并找到第一个严格大于的元素。如果不存在这样的元素,则返回 -1。
一个有效的解决方案是使用二分搜索。在一般的二分搜索中,我们正在寻找出现在数组中的值。然而,有时我们需要找到第一个大于目标的元素。
要查看此算法是否正确,请考虑进行的每个比较。如果我们找到一个大于目标元素的元素,那么它和它上面的所有元素都不可能匹配,所以没有必要搜索那个区域。因此,我们可以搜索左半部分。如果我们发现一个元素比所讨论的元素小,那么它之前的任何元素也必须更大,所以它们不能是第一个更小的元素,所以我们不需要搜索它们。因此,中间元素是它可能出现的最后一个位置。
请注意,在每次迭代中,我们至少放弃了一半的剩余元素。如果 top 分支执行,那么 [low, (low + high) / 2] 范围内的元素都被丢弃,导致我们失去 floor((low + high) / 2) – low + 1 >= (low +高) / 2 – 低 = (高 – 低) / 2 个元素。
如果底部分支执行了,那么[(low + high) / 2 + 1, high]范围内的元素都被丢弃。这让我们失去了高 – 地板(低 + 高)/ 2 + 1 > = 高 – (低 + 高)/ 2 =(高 – 低)/ 2 个元素。
因此,我们最终会在这个过程的 O(lg n) 次迭代中找到小于目标的第一个元素。
C++
// C++ program to find first element that
// is strictly smaller than given target.
#include
using namespace std;
int next(int arr[], int target, int end)
{
// Minimum size of the array should be 1
if(end == 0) return -1;
// If target lies beyond the max element, than the index of strictly smaller
// value than target should be (end - 1)
if (target > arr[end - 1]) return end-1;
int start = 0;
int ans = -1;
while (start <= end)
{
int mid = (start + end) / 2;
// Move to the left side if the target is smaller
if (arr[mid] >= target)
{
end = mid - 1;
}
// Move right side
else
{
ans = mid;
start = mid + 1;
}
}
return ans;
}
// Driver code
int main()
{
int arr[] = { 1, 2, 3, 5, 8, 12 };
int n = sizeof(arr)/sizeof(arr[0]);
cout << (next(arr, 5, n));
return 0;
}
// This code is contributed by d-dalal
Java
// Java program to find first element that
// is strictly smaller than given target.
class GfG {
private static int next(int[] arr, int target)
{
int start = 0, end = arr.length-1;
// Minimum size of the array should be 1
if(end == 0) return -1;
// If target lies beyond the max element, than the index of strictly smaller
// value than target should be (end - 1)
if (target > arr[end]) return end;
int ans = -1;
while (start <= end) {
int mid = (start + end) / 2;
// Move to the left side if the target is smaller
if (arr[mid] >= target) {
end = mid - 1;
}
// Move right side
else {
ans = mid;
start = mid + 1;
}
}
return ans;
}
// Driver code
public static void main(String[] args)
{
int[] arr = { 1, 2, 3, 5, 8, 12 };
System.out.println(next(arr, 5));
}
}
Python3
# Python3 program to find first element that
# is strictly smaller than given target
def next(arr, target):
start = 0;
end = len(arr) - 1;
# Minimum size of the array should be 1
if (end == 0):
return -1;
'''
If target lies beyond the max element, than the index of strictly smaller
value than target should be (end - 1)
'''
if (target > arr[end]):
return end;
ans = -1;
while (start <= end):
mid = (start + end) // 2;
# Move to the left side if target is
# smaller
if (arr[mid] >= target):
end = mid - 1;
# Move right side
else:
ans = mid;
start = mid + 1;
return ans;
# Driver code
if __name__ == '__main__':
arr = [ 1, 2, 3, 5, 8, 12 ];
print(next(arr, 5));
# This code is contributed by d-dalal
C#
// C# program to find first element that
// is strictly smaller than given target.
using System;
class GfG {
private static int next(int[] arr, int target)
{
int start = 0, end = arr.Length-1;
// Minimum size of the array should be 1
if(end == 0) return -1;
// If target lies beyond the max element, than the index of strictly smaller
// value than target should be (end - 1)
if (target > arr[end]) return end;
int ans = -1;
while (start <= end) {
int mid = (start + end) / 2;
// Move to the left side if the target is smaller
if (arr[mid] >= target) {
end = mid - 1;
}
// Move right side
else {
ans = mid;
start = mid + 1;
}
}
return ans;
}
// Driver code
public static void Main()
{
int[] arr = { 1, 2, 3, 5, 8, 12 };
Console.WriteLine(next(arr, 5));
}
}
// This code is contributed by d-dalal.
PHP
$arr[$end]) return $end;
$ans = -1;
while ($start <= $end)
{
$mid =(int)(($start + $end) / 2);
// Move to the left side if the target is smaller
if ($arr[$mid] >= $target)
{
$end = $mid - 1;
}
// Move right side
else
{
$ans = $mid;
$start = $mid + 1;
}
}
return $ans;
}
// Driver code
{
$arr = array(1, 2, 3, 5, 8, 12 );
echo(next0($arr, 5));
}
// This code is contributed by d-dalal.
2
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。