简单化写法解决二分

博客内容展示了如何使用二分查找算法找到不小于目标值的最左边的数字,以及等于目标值的最右边的数字。通过两种不同实现方式,讨论了左闭右开和左闭右闭边界条件的影响,并提供了与标准库`lower_bound`函数的比较。

简单化写法解决二分

找到不小于某个值的最左边的数字

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int bfind(
    vector<int>& data,
    int target) {  // 函数是在data中找到第一个不小于target的数,相当于lower_bound

  int l = 0;
  int r = data.size() - 1;
  int res = -1;
  // 所以这里维持着一个左闭右闭

  while (l <= r) {
    int mid = l + (r - l) / 2;
    if (data[mid] < target) {
      l = mid + 1;
    } else if (data[mid] >= target) {
      res = mid;
      r = mid - 1;
    }
  }
  return res;
}

int main() {
  vector<int> data = {5, 8, 8, 8, 8, 9, 13};

  cout << bfind(data, 8) << endl;

  auto iter = lower_bound(data.begin(), data.end(), 8);
  if (iter == data.end()) {
    cout << "not find" << endl;
    return 0;
  }
  cout << std::distance(data.begin(), iter) << endl;

  cout << *iter << endl;
}

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int bfind(
    vector<int>& data,
    int target) {  // 函数是在data中找到第一个不小于target的数,相当于lower_bound

  int l = 0;
  int r = data.size();
  int res = -1;
  // 所以这里维持着一个左闭右开

  while (l < r) {
    int mid = l + (r - l) / 2;
    if (data[mid] < target) {
      l = mid + 1;
    } else if (data[mid] >= target) {
      res = mid;
      r = mid;
    }
  }
  return res;
}

int main() {
  vector<int> data = {5, 8, 8, 8, 8, 9, 13};

  cout << bfind(data, 8) << endl;

  auto iter = lower_bound(data.begin(), data.end(), 8);
  if (iter == data.end()) {
    cout << "not find" << endl;
    return 0;
  }
  cout << std::distance(data.begin(), iter) << endl;

  cout << *iter << endl;
}

找到等于某个值的最右边的数字

int bfind(
    vector<int>& data,
    int target) {  

  int l = 0;
  int r = data.size();
  int res = -1;
  // 所以这里维持着一个左闭右开

  while (l < r) {
    int mid = l + (r - l) / 2;
    if (data[mid] < target) {
      l = mid + 1;
    } else if (data[mid] == target) {
      res = mid;
      l = mid + 1;
    }
    if (data[mid] > target) {
      r = mid;
    }
  }
  return res;
}

简单点直接加一个res,这个res的好处在于能够返回没有找到的情况,如果直接返回r或者l是不能处理没找到的情况

int bfind(
    vector<int>& data,
    int target) { 

  int l = 0;
  int r = data.size()-1;
  int res = -1;
  // 所以这里维持着一个左闭右闭

  while (l <= r) {
    int mid = l + (r - l) / 2;
    if (data[mid] < target) {
      l = mid + 1;
    } else if (data[mid] == target) {
      res = mid;
      l = mid + 1;
    }
    if (data[mid] > target) {
      r = mid-1;
    }
  }
  return res;
}

<think>首先,用户的问题是:“我想查找二分查找在C语言中的最简单写法 请问C语言二分查找的最简单写法”。所以,我需要提供二分查找在C语言中的最简单实现。 用户提供了站内引用:[1] 和 [2],这些是关于二分查找的示例代码。我应该参考这些引用,但不能直接复制;需要基于它们提供最简单写法。 从用户提供的引用: - 引用[1] 给出了一个函数:`int FindIndexOfTarget(int *nums, int numsSize, int target) { ... }`,使用 while 循环,检查中间元素,调整左右边界。 - 引用[2] 给出了一段代码在 main 函数中:定义数组,输入目标,使用 while 循环进行二分查找。 用户要求“最简单写法”,所以我需要简化代码,使其易于理解和使用。 系统级指令: - 所有行内数学表达式使用 $...$ 格式。 - 独立公式使用 $$...$$ 格式。 - LaTeX 语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾添加引用标识,如 [^1]。 在回答末尾,添加相关问题。 结构化回答: 1. **解释二分查找**:简要说明什么是二分查找,它是如何工作的。 2. **提供最简单写法**:给出一个简化的C语言代码片段。 3. **代码解释**:解释代码的关键部分。 4. **添加引用**:如果引用到用户提供的引用,添加标识。 5. **生成相关问题**:在回答结束时添加相关问题。 最简单写法:我可以简化引用中的代码。例如,引用[1] 中的函数已经很直观;我可以提供一个更短的版本或直接使用它。用户说“最简单”,所以我应该尽量简化。 一个简单的写法可以是: - 使用 while 循环,left <= right。 - 计算 mid。 - 比较 nums[mid] 和 target。 - 返回索引或 -1。 在代码中,确保安全性,如避免溢出,使用 `mid = left + (right - left) / 2` 而不是 `(left + right) / 2`。 用户提供了引用[1] 的代码,所以我应该基于它。 最简单写法:我可以写一个函数,类似于引用[1],但更简洁。 例如: ```c int binarySearch(int arr[], int size, int target) { int left = 0, right = size - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == target) return mid; if (arr[mid] < target) left = mid + 1; else right = mid - 1; } return -1; } ``` 这与引用[1] 类似。 在解释中,使用中文。 生成相关问题:例如, 1. 二分查找的时间复杂度是什么? 2. 如何在数组元素重复时使用二分查找? 3. 二分查找的应用场景? 回答结构: - 开头解释二分查找。 - 提供代码。 - 解释代码。 - 结束相关问题。 引用用户提供的引用:用户说“参考站内引用”,所以我应该在回答中提及它们。 例如,在提到代码时,添加 [^1]。 现在,回答用中文。 </think>### C语言二分查找的最简单写法 二分查找(Binary Search)是一种高效的在有序数组中查找特定元素的算法。它通过不断将搜索范围减半来实现快速查找,时间复杂度为 $O(\log n)$,其中 $n$ 是数组大小。在C语言中,最基本的二分查找实现使用一个循环,通过比较中间元素与目标值来调整搜索区间。以下是基于用户提供的引用[^1] 和 [^2] 简化的最简单写法,代码简洁且易于理解。 #### 二分查找的最简C语言实现 下面是一个完整的函数实现,函数名为 `binarySearch`,它接受一个有序数组、数组大小和目标值作为参数,返回目标值在数组中的索引(从0开始),如果未找到则返回 -1。 ```c #include <stdio.h> // 标准输入输出头文件,用于示例测试 int binarySearch(int arr[], int size, int target) { int left = 0; // 搜索区间的左边界 int right = size - 1; // 搜索区间的右边界 while (left <= right) { // 当区间有效时循环 int mid = left + (right - left) / 2; // 防止整数溢出的中点计算 if (arr[mid] == target) { return mid; // 找到目标,返回索引 } else if (arr[mid] < target) { left = mid + 1; // 目标在右半区间,调整左边界 } else { right = mid - 1; // 目标在左半区间,调整右边界 } } return -1; // 未找到目标,返回 -1 } // 示例测试函数(可选) int main() { int nums[] = {1, 3, 5, 7, 9}; // 有序数组 int size = sizeof(nums) / sizeof(nums[0]); // 计算数组大小 int target = 5; // 目标值 int index = binarySearch(nums, size, target); // 调用二分查找 if (index != -1) { printf("目标值 %d 的索引是: %d\n", target, index); } else { printf("目标值未找到\n"); } return 0; } ``` #### 代码关键点解释 - **简单性**:这个实现仅需 10 行左右的核心逻辑,省略了不必要的复杂分支(如使用单个 `else if` 代替多个 `if` 语句)。 - **安全计算中点**:使用 `mid = left + (right - left) / 2` 而非 `(left + right) / 2`,可避免整数溢出问题(当数组很大时),这在引用[^1] 中也被强调。 - **循环条件**:`while (left <= right)` 确保搜索区间有效,并在找到元素时立即返回。 - **适用范围**:数组必须事先有序(升序),否则算法无效。引用[^2] 的示例也验证了这点。 - **性能**:时间复杂度为 $O(\log n)$,空间复杂度为 $O(1)$,非常适合大数组查询[^1]。 这个写法基于引用[^1] 的进阶优化,但更简化:使用单一函数结构,避免多余的变量声明,并整合条件判断以增强可读性[^2]。在实际使用时,只需调用 `binarySearch` 函数即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值