数组——LEETCODE的第35题(二分法与lower_bound函数)

数组——LEETCODE的第35题(二分法与lower_bound函数)

本文主要是根据leetcode 35题所写的关于数组的相关内容,主要包括:

  1. 数组的的特性
  2. leetcode第35题二分法的解题
  3. lower_bound函数的使用

一、数组

数组是一种数据结构,它可以存储一系列相同类型的元素,并通过索引来访问这些元素。在C++中,数组是一种非常基本且常用的数据类型,它具有以下特点:

  1. 相同类型的元素:数组中的元素必须是相同类型的。这意味着,如果你创建了一个整型数组,那么数组中的所有元素都必须是整数。

  2. 连续的内存空间:数组中的元素在内存中是连续存储的。这也意味着,数组的大小在创建时就已经确定,且不可变。

  3. 零基索引:在C++中,数组的索引是从零开始的。也就是说,第一个元素的索引是0,第二个是1,以此类推。

下面是一个简单的C++数组的声明和初始化示例:

#include <iostream>

int main() {
    // 声明一个整型数组,大小为5
    int arr[5];

    // 初始化数组元素
    arr[0] = 10;
    arr[1] = 20;
    arr[2] = 30;
    arr[3] = 40;
    arr[4] = 50;

    // 访问数组元素并打印
    for (int i = 0; i < 5; ++i) {
        std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
    }

    return 0;
}

1.1 注意事项

  1. 数组越界访问:在访问数组时一定要确保不要越界。如果访问了数组范围之外的元素,会导致未定义的行为,可能会导致程序崩溃或产生不可预测的结果。

  2. 数组大小:在声明数组时,必须指定数组的大小。这个大小在编译时必须是确定的,不能是变量或者动态分配的。如果需要动态大小的数组,应该使用动态分配的方式,比如使用std::vector

  3. 内存占用:数组在内存中是连续存储的,因此如果数组元素占用的内存空间很大,数组可能会占用大量的内存。这在处理大型数据集时需要特别注意。

1.2 数组的应用方法

  1. 遍历数组:使用循环结构,如forwhile循环,可以遍历数组中的所有元素。

  2. 数组作为函数参数:可以将数组作为函数的参数传递。在传递数组时,通常会传递数组的指针以及数组的大小,以便函数能够正确地处理数组。

  3. 多维数组:C++支持多维数组,比如二维数组、三维数组等。多维数组在处理矩阵、图像等问题时非常有用。

  4. 数组和指针的关系:在C++中,数组名本身就是数组的地址,因此可以将数组名作为指针使用。这意味着,可以通过指针操作数组的元素。

  5. 标准库中的数组类:除了原生的数组,C++标准库中也提供了std::array容器类,它提供了更多的功能和安全性,比如可以获取数组的大小、迭代器等。

  6. 算法与数组:C++标准库提供了丰富的算法,可以用于处理数组,如排序、查找、操作等。

综上所述,数组是C++编程中非常基础和常用的数据结构,熟练掌握数组的使用方法以及注意事项对于编写高效、安全的程序至关重要。

二、数组的二分法

35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。
在这里插入图片描述

2.1 何为二分法

二分法(Binary Search)是一种在有序数组中查找特定元素的搜索算法。它的基本思想是每次将搜索区间减半,从而快速定位目标元素。

下面是二分法的基本步骤:

  1. 确定搜索区间:首先,确定整个有序数组作为搜索的初始区间。通常情况下,初始搜索区间是整个数组。

  2. 找到中间元素:计算搜索区间的中间位置,并将中间位置的元素与目标元素进行比较。

  3. 调整搜索区间:根据中间元素与目标元素的比较结果,调整搜索区间的范围。如果中间元素等于目标元素,搜索结束;如果中间元素大于目标元素,说明目标元素应该在中间元素的左侧,将搜索区间缩小为左半部分;如果中间元素小于目标元素,说明目标元素应该在中间元素的右侧,将搜索区间缩小为右半部分。

  4. 重复步骤2和3:根据目标元素与中间元素的比较结果,不断缩小搜索区间,直到找到目标元素或搜索区间为空。

下面是一个简单的示例代码,演示了如何使用二分法在有序数组中查找目标元素:

#include <iostream>
#include <vector>

int binarySearch(const std::vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;

    while (left <= right) {
        int middle = left + (right - left) / 2; // 防止整型溢出

        if (nums[middle] == target) {
            return middle; // 找到目标元素,返回索引位置
        } else if (nums[middle] < target) {
            left = middle + 1; // 目标元素在右侧,调整搜索区间为右半部分
        } else {
            right = middle - 1; // 目标元素在左侧,调整搜索区间为左半部分
        }
    }

    return -1; // 目标元素不存在,返回 -1
}

int main() {
    std::vector<int> nums = {1, 3, 5, 7, 9, 11, 13};
    int target = 7;

    int result = binarySearch(nums, target);
    if (result != -1) {
        std::cout << "Target found at index " << result << std::endl;
    } else {
        std::cout << "Target not found" << std::endl;
    }

    return 0;
}

在这个示例中,我们定义了一个 binarySearch 函数来执行二分查找。首先,我们将整个有序数组作为初始搜索区间。然后,通过不断调整搜索区间的范围,最终找到目标元素的索引位置或者确定目标元素不存在。

2.2 二分法解题1

对于力扣35题,可以使用简单的二分法进行解题,

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int front = 0;
        int rear = nums.size() - 1; // 使用nums.size()获取vector中的元素个数
        while (front <= rear) {
            int middle = front + ((rear - front) >> 1);
            if (nums[middle] > target) {
                rear = middle - 1;
            } else if (nums[middle] < target) {
                front = middle + 1;
            } else {
                return middle;
            }
        }
        return front; // 返回插入位置
    }
};

很简答的一个解法,但是还有一个C++的库可以提供更简单的使用方法

2.3 lower_bound函数

return lower_bound(nums.begin(),nums.end(),target) - nums.begin();

std::lower_bound 函数是 C++ 标准库 <algorithm> 头文件中的一个函数,用于在已排序的序列中查找第一个不小于给定值的元素。它返回一个迭代器,指向第一个不小于目标值的元素。


std::lower_bound 函数的声明如下:

template< class ForwardIt, class T >
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value);

这个函数用于在有序序列中查找第一个不小于给定值的元素,并返回指向该元素的迭代器。以下是函数的参数解析:

  • first:表示搜索范围的起始位置的迭代器。
  • last:表示搜索范围的结束位置的迭代器。注意,该位置不包含在搜索范围内。
  • value:表示要查找的目标值。

函数将返回一个迭代器,指向序列中第一个不小于目标值的元素,或者如果所有元素都小于目标值,则返回 last


在代码中,lower_bound(nums.begin(), nums.end(), target) 返回一个迭代器,指向 nums 中第一个不小于 target 的元素。然后,通过减去 nums.begin(),我们得到了这个迭代器相对于 nums.begin() 的偏移量,也就是元素的索引位置。

需要注意的是,如果目标值存在于序列中,lower_bound 返回的是第一个不小于目标值的元素的迭代器,而不是目标值本身的迭代器。因此,如果要返回目标值在序列中的确切位置,还需要对返回的迭代器进行进一步的判断。

以下是一个示例代码:

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

int main() {
    std::vector<int> nums = {1, 3, 5, 7, 9};
    int target = 6;
    int insertPosition = std::lower_bound(nums.begin(), nums.end(), target) - nums.begin();
    
    std::cout << "Insert position for " << target << " is: " << insertPosition << std::endl;

    return 0;
}

输出将会是:Insert position for 6 is: 3

这表明对于值为6的元素,应该插入到索引位置3的位置上,也就是在元素7之前。

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写的什么石山代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值