C++刷题笔记(2)——leetcode27、26、283

2024-02-02 19:32
文章标签 c++ 笔记 刷题 26 283 leetcode27

本文主要是介绍C++刷题笔记(2)——leetcode27、26、283,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

双指针法

双指针法利用两个指针对数组进行扫描,利用问题本身所给的序列特性(升序或降序),通常是相反方向的或者相同方向不同速度(快慢指针)

并非是一种算法,更像是一种变成技巧;

快慢指针中,在慢指针循环内定义快指针,快指针在慢指针之前,对数组后续元素依次扫描,在扫描到指定元素或者数组结尾的时候快指针返回,慢指针后移,并且根据题目要求移动或替换元素。

题目1:27.移除元素在这里插入图片描述

数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖

暴力解法

两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组
在这里插入图片描述
暴力算法的解题思路很简单,就是遍历数组找到目标元素,然后依次移动目标元素后面的元素将其覆盖

class Solution {
public:int removeElement(vector<int>& nums, int val) {int size = nums.size();for (int i = 0; i < nums.size(); i++) {            //遍历数组if (nums[i] == val) {                          //发现需要移除的元素for (int j = i + 1; j < size; j++) {       //就将数组集体向前移动一位nums[j - 1] = nums[j];             }i--;                                       //因为下标i以后的数值都向前移动了一位,所以i也向前移动一位size--;                                    //此时数组的大小-1}}return size;}
};

双指针法

在这里插入图片描述
当碰到target数值,慢指针停止移动,快指针保持移动,并把快指针指向的数组元素移动到慢指针
单向双指针方法:
没有改变数组中元素的相对位置

//单向双指针
class Solution {
public:int removeElement(vector<int>& nums, int val) {int i = 0;                                         //i为慢指针for (int j = 0; j < nums.size() - 1; j++) {        //j为快指针,这里不能写j < nums.size() - 1,防止数组长度为1和0if (val != nums[j]) {nums[i++] = nums[j];                      //nums中的j元素如果不等于val,则慢指针后移一位,快指针后移一位}}                                                //若j等于val,则再次进入循环体,快指针后移,慢指针不动return i;}
};

单向双指针方法解题思路:
在这里插入图片描述
首先就是快指针、慢指针的索引初始为0,根据循环条件j < nums.size()进入循环,寻找数组中等于目标值的元素,这里要注意后置递增是先计算表达式、再对变量进行加1
在这里插入图片描述
直到i=2、j=2,此时j的值仍满足循环条件,但不满足if语句,因此不会执行if语句,直接执行j++,j=3
在这里插入图片描述
再次进行循环,j=3,满足循环条件且满足if语句,此时j=3、i=2,执行if语句会将进行赋值操作nums[2] = nums[3]; 完成移除元素操作
在这里插入图片描述
之后会依次将快指针的值赋给慢指针
在这里插入图片描述
当i=3、j=4时依然满足循环条件和if语句条件,继续进行一个循环后i=4、j=5,不再满足循环条件,返回i,返回移除后数组的新长度。
在这里插入图片描述

双向指针方法:
基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素

class Solution {
public:int removeElement(vector<int>& nums, int val) {int i = 0;                                      //左指针int j = nums.size() - 1;                        //右指针while (i <= j) {                                while (i <= j && nums[i] != val) {          //找左边等于val的元素,如果这里不加i <= j的限制,就可能i一直右移到j右边,造成数组长度不准确++i; }while (i <= j && nums[j] == val) {          //找右边不等于val的元素,这里i<=j同上--j;}if (i < j) {                                //将右边不等于val的元素覆盖左边等于val的元素,这里i<j没有等于,如果可以等于,那么执行i++、j--后同样i可能移动到j右边nums[i++] = nums[j--];}}return i;                                       //i一定指向了最终数组末尾的下一个元素}
};

双向指针方法解题思路:
在这里插入图片描述
这种解法的思路左指针从数组的左边开始遍历数组,寻找等于目标值的元素右指针从右开始遍历数组,寻找不等于目标值的元素
在这里插入图片描述
于是就有了等于目标值的元素的索引和正常的元素,用正常元素覆盖等于目标值的元素完成移除元素操作
在这里插入图片描述
之后左指针继续遍历数组,当左指针i=4时仍满足while (i <= j)while (i <= j && nums[i] != val)的循环条件,因此还会继续进行累加,累加后i=5,不再满足循环条件,返回i,返回移除后数组的新长度。
在这里插入图片描述

题目2:26.删除排序数组中的重复项

在这里插入图片描述
单向双指针方法:

class Solution {
public:int removeDuplicates(vector<int>& nums) {int i = 0;                                //i慢for (int j = 1; j < nums.size(); j++) {   //j快if (nums[i] != nums[j]) {i++;                              //移到下一位,将不同的数放入nums[i] = nums[j];}}return i + 1;                            //删除后数组的新长度}
};

单向双指针方法解题思路:
在这里插入图片描述
解题思路大概和27题差不多,当i=2、j=3时,将会跳过if语句,执行j++,此时i=2、j=4
在这里插入图片描述
继续执行代码i++;nums[i] = nums[j];(i=3,nums[3] = nums[4]),删除数组中的重复项,j++,此时i=3、j=5,不再满足循环条件,返回数组成都
在这里插入图片描述
然后进行j++,此时i=3、j=5,不再满足循环条件,返回数组长度。

题目3:283.移动零

在这里插入图片描述
这一题和27题非常的类似了
单向双指针方法:

class Solution {
public:void moveZeroes(vector<int>& nums) {int slowIndex = 0;for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {if (nums[fastIndex] != 0) {nums[slowIndex++] = nums[fastIndex];}}// 将slowIndex之后的冗余元素赋值为0for (int i = slowIndex; i < nums.size(); i++) {nums[i] = 0;}}
};

单向双指针方法解题思路:
主要解题思路就是用双指针遍历数组,当遇到0元素时,slowIndex不动,fastIndex+1,然后将快指针赋值给慢指针。

相当于对整个数组移除元素0,然后slowIndex之后都是移除元素0的冗余元素,把这些元素都赋值为0就可以了。

这篇关于C++刷题笔记(2)——leetcode27、26、283的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/671727

相关文章

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

使用C/C++调用libcurl调试消息的方式

《使用C/C++调用libcurl调试消息的方式》在使用C/C++调用libcurl进行HTTP请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试,libcurl提供了多种... 目录1. libcurl 调试工具简介2. 输出请求消息使用 CURLOPT_VERBOSE使用 C

C++实现获取本机MAC地址与IP地址

《C++实现获取本机MAC地址与IP地址》这篇文章主要为大家详细介绍了C++实现获取本机MAC地址与IP地址的两种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实际工作中,项目上常常需要获取本机的IP地址和MAC地址,在此使用两种方案获取1.MFC中获取IP和MAC地址获取

C/C++通过IP获取局域网网卡MAC地址

《C/C++通过IP获取局域网网卡MAC地址》这篇文章主要为大家详细介绍了C++如何通过Win32API函数SendARP从IP地址获取局域网内网卡的MAC地址,感兴趣的小伙伴可以跟随小编一起学习一下... C/C++通过IP获取局域网网卡MAC地址通过win32 SendARP获取MAC地址代码#i