目录

  • 数组理论基础、二分查找、移除元素
    • 1.数组理论基础
    • 2.Leetcode704.二分查找
      • 方法一 左闭右闭:
      • 方法二 左闭右开:
      • 方法三 左开右开:
      • 方法四 左开右闭:
    • 3.Leetcode27. 移除元素
      • 方法一 暴力解法
      • 方法二 双指针法

数组理论基础、二分查找、移除元素

1.数组理论基础

题目建议:了解数组基础,以及数组的内存空间地址

  • 数组是存放在连续内存空间上的相同类型数据的集合
  • 数组的元素是不能删的,只能覆盖:平时删除操作也是依次用后一位覆盖,因为申请且初始化后,存储空间就固定了

验证数组在内存的空间地址是否连续:

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。void test_arr() {          //创建一个3*3的二维数组,并打印内存地址int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};cout << &array[0][0] << " " << &array[0][1] << " " << &array[0][2] << endl;cout << &array[1][0] << " " << &array[1][1] << " " << &array[1][2] << endl;cout << &array[2][0] << " " << &array[2][1] << " " << &array[2][2] << endl;
};int main()
{test_arr();
}

输出的测试地址:

000000B846EFF668 000000B846EFF66C 000000B846EFF670
000000B846EFF674 000000B846EFF678 000000B846EFF67C
000000B846EFF680 000000B846EFF684 000000B846EFF688

2.Leetcode704.二分查找

题目建议: 掌握704.二分查找,先把 704写熟练,要熟悉 根据 左闭右开,左闭右闭 两种区间规则 写出来的二分法。拓展看一下:35.搜索插入位置 和 34. 在排序数组中查找元素的第一个和最后一个位置

思路:

  • 二分法的前提条件:1.数组为有序数组 2.数组中无重复元素
  • 循环不变量规则区间的定义就是不变量,在while寻找中每一次边界的处理都要坚持根据区间的定义来操作
  • 写二分法,区间的定义一般为两种:左闭右闭即[left, right],或者左闭右开即[left, right)。
方法一 左闭右闭:
//方法一 力扣一次AC
class Solution {public:int search(vector<int>& nums, int target) {int left =0;int right=nums.size()-1;  // 定义target在左闭右闭的区间里,[left, right],根据区间定义让所有元素在该区间内while(left <= right){     // 当left==right,区间[left, right]依然有效,所以用 <=   例:[2,2]int mid=left + ((right - left) / 2); // 防止溢出 等同于(left + right)/2if(nums[mid]>target){right=mid-1;      // target 在左区间,所以[left, middle - 1]}else if(nums[mid]<target){left=mid+1;       // target 在右区间,所以[middle + 1, right]}       else{                // nums[middle] == targetreturn mid;      // 数组中找到目标值,直接返回下标}}return -1;              //未找到目标值}
};
  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)
方法二 左闭右开:
//方法二 力扣一次AC
class Solution {public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size();      // 定义target在左闭右开的区间里,即:[left, right) 根据区间定义让所有元素在该区间内while (left < right){          // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <  例:[2,2)int mid = left + (right-left)/2;// 防止溢出 等同于(left + right)/2if (nums[mid] > target){right = mid;        // target 在左区间,在[left, middle)中}else if (nums[mid] < target){left = mid + 1;        // target 在右区间,在[middle + 1, right)中}else{                   // nums[middle] == targetreturn mid;         // 数组中找到目标值,直接返回下标}}return -1 ;                  //未找到目标值}
};
  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)
方法三 左开右开:
// 方法三 左开右开 未考虑区间定义,超出内存限制一次
class Solution {public:int search(vector<int>& nums, int target) {int left = -1;int right = nums.size();while (left < right-1){    //这里一定考虑区间是否有意义 例如:(2,3)也是没有意义的int mid = left + (right-left)/2;if (nums[mid] > target){right = mid;}else if (nums[mid] < target){left = mid ;}else{return mid;}}return -1 ;}
};
方法四 左开右闭:
class Solution {public:int search(vector<int>& nums, int target) {int left = -1;int right = nums.size()-1;while (left < right){int mid = ( (left + right + 1) / 2) ;if (nums[mid] > target){right = mid -1;}else if (nums[mid] < target){left = mid ;}else{return mid ;}}return -1 ;}
};

3.Leetcode27. 移除元素

题目建议: 27.移除元素,暴力的解法,可以锻炼一下我们的代码实现能力,建议先把暴力写法写一遍。 双指针法 是本题的精髓,今日需要掌握,至于拓展题目可以先不看。

思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。

方法一 暴力解法

这个题目暴力的解法就是两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。

class Solution {public:int removeElement(vector<int>& nums, int val) {int size = nums.size();for(int i=0;i < size;i++){if(nums[i]==val){         // 发现需要移除的元素,就将数组集体向前移动一位for(int j=i+1;j<size;j++){   //从i后面一位开始往前移一位nums[j-1]=nums[j];}i--;     // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位size--;  // 此时数组的大小-1}}return size;}
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
方法二 双指针法

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作

双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。

class Solution {public:int removeElement(vector<int>& nums, int val) {int size = nums.size();int slow = 0;for(int i =0;i < size;i++){if(nums[i]!=val){nums[slow]=nums[i];slow++;}}return slow;}
};
/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {public:int removeElement(vector<int>& nums, int val) {int leftIndex = 0;int rightIndex = nums.size() - 1;while (leftIndex <= rightIndex) {// 找左边等于val的元素while (leftIndex <= rightIndex && nums[leftIndex] != val){++leftIndex;}// 找右边不等于val的元素while (leftIndex <= rightIndex && nums[rightIndex] == val) {-- rightIndex;}// 将右边不等于val的元素覆盖左边等于val的元素if (leftIndex < rightIndex) {nums[leftIndex++] = nums[rightIndex--];}}return leftIndex;   // leftIndex一定指向了最终数组末尾的下一个元素}
};

代码随想录Day01:数组理论基础、二分查找、移除元素相关推荐

  1. 代码随想录第一天| 704. 二分查找、27. 移除元素

    数组相关知识 数组下标都是从0开始的. 数组内存空间的地址是连续的 因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址. go声明二维数组时,系统 ...

  2. 第一天 :二分查找+移除元素

    数组基础 数组在内存空间的地址是连续的 数组下标都是从0开始 数组元素不能删,只能覆盖 二分查找 题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数 ...

  3. leetcode练习一:数组(二分查找、双指针、滑动窗口)

    文章目录 一. 数组理论基础 二. 二分查找 2.1 解题思路 2.2 练习题 2.2.1 二分查找(题704) 2.2.2 搜索插入位置(题35) 2.2.3 查找排序数组元素起止位置(题34) 2 ...

  4. 【代码随想录】数组刷题

    数组刷题 二分 二分查找* 搜索插入位置 在排序数组中查找元素的第一个和最后一个位置* x 的平方根 有效的完全平方数 双指针 移除元素 删除排序数组中的重复项 移动零 比较含退格的字符串 有序数组的 ...

  5. Python算法二分查找之重复元素列表

    描述: 请实现有重复数字的升序数组的二分查找 给定一个 元素有序的(升序)长度为n的整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的第一个出现的target,如果目标 ...

  6. 【C语言函数3.2】写一个函数,实现一个整形有序数组的二分查找代码

    写一个函数,实现一个整形有序数组的二分查找代码 #include <stdio.h>int binary_search(int a[], int k, int s) {int left = ...

  7. (旋转数组的)二分查找算法

    二分查找算法(Binary Search)是一种高效的.应用广泛的查找算法.它是一种采用分治策略的算法. 基本二分查找算法 二分查找是针对顺序存储的有序序列的:二分查找的基本思想是:将目标元素与序列中 ...

  8. 开花(在b数组中二分查找a数组元素)

    注意: 代码一:二层循环暴力查找超时 代码二(最棒):借用STL set中的count()方法快速搞定,且没有超时so,集合查询应该很快注意:count()时间复杂度是线性变换的最坏的情况为O(n)s ...

  9. 筑基_C_5_对数组的二分查找

    对数组的二分查找 1 泛型函数bsearch()的编写过程 1.1 先实现对整型数组的查找 1.2 尝试使用泛型 1.3 增加对负数和指针数组的支持 2 测试 2.1 对指针数组的二分查找 1 泛型函 ...

  10. 有序升序数组的二分查找

    有序升序数组的二分查找 //有序升序数组二分查找 #include<stdio.h> #include<windows.h> //控制台显示 int BinSearch(int ...

最新文章

  1. IOS学习笔记(四)之UITextField和UITextView控件学习
  2. 编写UEditor插件
  3. 【Node.js】http-server 实现目录浏览服务
  4. matlab 三维绘图 抛光,瓷砖抛光过程建模与仿真
  5. VS code前端配置
  6. 程序员:站在自学鄙视链顶端的王者(太真实!)
  7. 深度优先搜索-和为某数的所有组合
  8. Java里什么是面向对象?
  9. 返回结果乱码_峰哥说技术系列-7 Spring Boot返回JSON
  10. android gps 获取方位_Android GPS定位 获取经纬度
  11. UINO优锘:数据中心可视化管理面向运营的IT运维配置管理
  12. MCU控制继电器的电路详解
  13. arduino密码锁代码
  14. 基于Python热点新闻关键词数据分析系统
  15. OpenStack安装Placement组件部署(四)
  16. CF1091F New Year and the Mallard Expedition
  17. [CF1131F] Asya And Kittens
  18. gamepad android手柄,经验篇,游戏手柄使用教程,刀锋游戏手柄连接安卓苹果手机设置方法...
  19. LORa 无线压力传感器在智慧城市中的应用
  20. 如何正确地在vm虚拟机中安装Linux 显卡

热门文章

  1. STM32 RTC应用 内部唤醒中断 (Internal Wakeup)
  2. jieba库的安装与使用
  3. 方程求根的迭代法——牛顿迭代法
  4. 修改数据库账号密码(最新版本)
  5. (学习笔记)PCL点云库的基本使用
  6. ubuntu18.04安装pcl库
  7. 项目分享-限流框架的实现
  8. npm,nodejs如何升级
  9. STM32OLED显示-学习笔记
  10. 可维护性、可复用性和可扩展性的区别