代码随想录Day01:数组理论基础、二分查找、移除元素
目录
- 数组理论基础、二分查找、移除元素
- 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:数组理论基础、二分查找、移除元素相关推荐
- 代码随想录第一天| 704. 二分查找、27. 移除元素
数组相关知识 数组下标都是从0开始的. 数组内存空间的地址是连续的 因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址. go声明二维数组时,系统 ...
- 第一天 :二分查找+移除元素
数组基础 数组在内存空间的地址是连续的 数组下标都是从0开始 数组元素不能删,只能覆盖 二分查找 题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数 ...
- leetcode练习一:数组(二分查找、双指针、滑动窗口)
文章目录 一. 数组理论基础 二. 二分查找 2.1 解题思路 2.2 练习题 2.2.1 二分查找(题704) 2.2.2 搜索插入位置(题35) 2.2.3 查找排序数组元素起止位置(题34) 2 ...
- 【代码随想录】数组刷题
数组刷题 二分 二分查找* 搜索插入位置 在排序数组中查找元素的第一个和最后一个位置* x 的平方根 有效的完全平方数 双指针 移除元素 删除排序数组中的重复项 移动零 比较含退格的字符串 有序数组的 ...
- Python算法二分查找之重复元素列表
描述: 请实现有重复数字的升序数组的二分查找 给定一个 元素有序的(升序)长度为n的整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的第一个出现的target,如果目标 ...
- 【C语言函数3.2】写一个函数,实现一个整形有序数组的二分查找代码
写一个函数,实现一个整形有序数组的二分查找代码 #include <stdio.h>int binary_search(int a[], int k, int s) {int left = ...
- (旋转数组的)二分查找算法
二分查找算法(Binary Search)是一种高效的.应用广泛的查找算法.它是一种采用分治策略的算法. 基本二分查找算法 二分查找是针对顺序存储的有序序列的:二分查找的基本思想是:将目标元素与序列中 ...
- 开花(在b数组中二分查找a数组元素)
注意: 代码一:二层循环暴力查找超时 代码二(最棒):借用STL set中的count()方法快速搞定,且没有超时so,集合查询应该很快注意:count()时间复杂度是线性变换的最坏的情况为O(n)s ...
- 筑基_C_5_对数组的二分查找
对数组的二分查找 1 泛型函数bsearch()的编写过程 1.1 先实现对整型数组的查找 1.2 尝试使用泛型 1.3 增加对负数和指针数组的支持 2 测试 2.1 对指针数组的二分查找 1 泛型函 ...
- 有序升序数组的二分查找
有序升序数组的二分查找 //有序升序数组二分查找 #include<stdio.h> #include<windows.h> //控制台显示 int BinSearch(int ...
最新文章
- IOS学习笔记(四)之UITextField和UITextView控件学习
- 编写UEditor插件
- 【Node.js】http-server 实现目录浏览服务
- matlab 三维绘图 抛光,瓷砖抛光过程建模与仿真
- VS code前端配置
- 程序员:站在自学鄙视链顶端的王者(太真实!)
- 深度优先搜索-和为某数的所有组合
- Java里什么是面向对象?
- 返回结果乱码_峰哥说技术系列-7 Spring Boot返回JSON
- android gps 获取方位_Android GPS定位 获取经纬度
- UINO优锘:数据中心可视化管理面向运营的IT运维配置管理
- MCU控制继电器的电路详解
- arduino密码锁代码
- 基于Python热点新闻关键词数据分析系统
- OpenStack安装Placement组件部署(四)
- CF1091F New Year and the Mallard Expedition
- [CF1131F] Asya And Kittens
- gamepad android手柄,经验篇,游戏手柄使用教程,刀锋游戏手柄连接安卓苹果手机设置方法...
- LORa 无线压力传感器在智慧城市中的应用
- 如何正确地在vm虚拟机中安装Linux 显卡