C++ day1 数组理论基础,704. 二分查找,27. 移除元素

基础知识

数组是存放在连续内存空间上的相同类型数据的集合

数组的元素是不能删的,只能覆盖,如果想要使用移除元素的库函数,可以使用vector中的erase函数删除数组中的某某元素,但是要注意,这里的erase操作,也是一个覆盖的过程,后面的数据一个挨一个覆盖前面删除数据的位置,因此这是一个O(n)操作,不是O(1)操作.

题目1:704二分查找

题目链接:二分查找

对题目的理解

数组是有序数组,且数组中没有重复的元素,这也是二分法使用的前提条件

自己的思路

遍历数组中的每个元素,比较nums数组中每个元素与target是否相等,若相等,输出该元素对应的下标;如果遍历所有的元素都没有相等的值,则输出-1

自己的解法(比较暴力)

对于自己想出的这种简单粗暴的解法,还有两个疑问

Q1 : 就是题目给出的示例中,并没有输入数组中含有多少个元素,这里数组的定义如何解决?

A:leecode中已经给出了定义的类和数组,在里面书写即可。

Q2 :就是最终如果数组中没有元素与target相等的话,那最终的-1怎么输出?

A:这个最后在循环之外返回-1就好啦。

与题目中给的有序条件没有用上。时间复杂度高,不推荐。

class Solution {
public:
    int search(vector& nums, int target) {
        for(int i=0;i

解法1:左闭右闭区间规则(熟悉)

定义 target 是在左闭右闭的区间[left, right] 里,那么此时需要满足两点:

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)
class Solution {
public:
    int search(vector& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        while(left<=right)
        {
            // int middle = (left+right)/2; 这样写可能会出现溢出的情况
            //int middle = left + ((right - left)/2);  //这样写更保险一点放止溢出
            int middle = left + ((right-left)>>1);//使用位运算效率会更高一些
            if(nums[middle]>target)
            {
                right = middle-1;
            }
            else if(nums[middle]

解法2:左闭右开区间规则(熟悉)

定义 target 是在一个在左闭右开的区间里,也就是[left, right),此时需要满足如下两点:

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 赋值为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)
class Solution {
public:
    int search(vector& nums, int target) {
        int left = 0;
        int right = nums.size();
        while(lefttarget)
            {
                right = middle;
            }
            else if(nums[middle]

题目2:移除元素

题目链接:移除元素

对题目的理解

原地移除所有值为val的元素,不使用额外的数组空间,元素顺序可以改变

自己的思路

遍历数组中所有的元素,将数组中的每一个元素与val比较,如果遇到相等的情况,则将该处的数据用下一个数据顶上,即nums[i]=nums[i+1],直到所有的元素都遍历完成。

这样粗暴的方法有两个疑问:

Q1:nums[i+1]该怎么处理?如果出现数据覆盖的情况,后面的数据应该都要移动,那这个批量移动该怎么办?

A1:可以在大循环里面,使用一个小循环,遍历后面的所有元素,将后面每一个元素赋值给对应的前一个元素。

Q2:最终输出的是既有数组的大小又有处理完之后的数组,这个输出有怎么解决?

A2:这个的话,内部将返回了数组的大小,做一个for循环,输出了数组。

解法1:暴力解法

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
第一段代码有错误,是因为nums.size是一个常量,所以,要使其发生变化做自减操作时,需要将其赋值给一个变量,对变量进行自减操作。
class Solution {
public:
    int removeElement(vector& nums, int val) {
        for(int i=0;i
对num.size()不能自减的问题进行了修改,将其赋值为一个int型变量,从而完成自减操作。
class Solution {
public:
    int removeElement(vector& nums, int val) {
        int nums_size = nums.size();
        for(int i=0;i

解法2:双指针法(精华★)

通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置
  • 时间复杂度:O(n)
  • 空间复杂度:O(1

这种方法并没有改变元素的相对位置。

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int slow = 0;
        for(int fast = 0;fast

总结

今天花了大概3个小时的时间学习了这些知识,掌握了有序无重复数组下的二分法解题以及双指针移除元素法,蛮有收获的

你可能感兴趣的:(c++,开发语言)