「双指针技巧解决一些数组问题」

news2024/10/6 18:26:57

文章目录

  • 0 分类
  • 1 快慢指针刷题
    • 1.1 删除有序数组中的重复项
      • 题解
      • Code
      • 结果
    • 1.2 删除排序链表中的重复元素
      • 题解
      • Code
      • 结果
    • 1.3 移除元素
      • 题解
      • Code
      • 结果
    • 1.4 移动0
      • 题解
      • Code
  • 2 左右指针刷题
    • 2.1 二分查找
    • 2.2 两数之和 II - 输入有序数组
      • 题解
      • Code
      • 结果
    • 2.3 反转字符串
      • 题解
      • Code
      • 结果
    • 2.4 最长回文子串
      • 题解
      • Code
      • 结果

0 分类

双指针分类为快慢指针,左右指针。左右指针,两个指针相向/背而行;快慢指针则是同向而行,一快一慢。

单链表很多都是快慢指针,之前已经写出过。

这次来看看双指针解决数组问题,另一大类的滑动窗口下次再说。

1 快慢指针刷题

1.1 删除有序数组中的重复项

在这里插入图片描述

题解

因为要原地修改数组,所以不能使用new一个新数组的方法,所以直接双指针技巧,一个慢指针slow,一个快指针fast,fast相当于在前面探路,当找到一个不重复的元素就赋值给slow,并且让slow往前走一步,这样进行原地修改即可,最后返回个数,因为是0~slow都是不重复的,所以个数应该是slow+1。

Code

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if (nums.size() == 0)
        {
            return 0;
        }
        int slow = 0, fast = 0;
        while (fast < nums.size())
        {
            if (nums[slow] != nums[fast])
            {
                ++slow;//移动到下一个坑位存储
                nums[slow] = nums[fast];
            }
            ++fast;
        }
        return slow + 1;//因为slow是从下标0开始的,所以要返回slow+1
    }
};

结果

在这里插入图片描述

1.2 删除排序链表中的重复元素

在这里插入图片描述

题解

其实将上述的方法拓展到链表中即可,还是快慢指针的技巧,一个快指针在前面探路,然后有不重复的直接把slow->next = fast即可。

Code

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head) return head;
        ListNode *slow = head, *fast = head;
        while (fast != nullptr)
        {
            if (fast->val != slow->val)
            {
                slow->next = fast;
                slow = slow->next;
            }
            fast = fast->next;
        }
        slow->next = nullptr;//最后断开重复的
        return head;
    }
};

结果

在这里插入图片描述

1.3 移除元素

在这里插入图片描述

题解

与第一题删除重复元素差不多,还是快慢指针的思路。

Code

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //int size = nums.size();
        int slow = 0, fast = 0;
        while (fast < nums.size())
        {
            if (nums[fast] != val)
            {
                nums[slow] = nums[fast];//这样就使得从0~slow这个区间,nums是不包含val的
                slow++;
            }
            fast++;
        }
        return slow;//0~slow不包含val,此时返回slow就行,就是个数
    }
};

所以归类出一个删除重复元素的模板:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //int size = nums.size();
        int slow = 0, fast = 0;
        while (fast < nums.size())
        {
            if (nums[fast] != val)
            {
                nums[slow] = nums[fast];//这样就使得从0~slow这个区间,nums是不包含val的
                slow++;
            }
            fast++;
        }
        return slow;//0~slow不包含val,此时返回slow就行,就是个数
    }
};

结果

在这里插入图片描述

1.4 移动0

在这里插入图片描述

题解

采用上述的删除模板,先把0全部删除,之后再进行末尾补0即可。

Code

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int p = removeElement(nums, 0);//去除0之后的数组长度
        for (; p < nums.size(); ++p)
        {
            nums[p] = 0;
        }
    }

    int removeElement(vector<int>& nums, int val)//
    {
        int fast = 0, slow = 0;
        while (fast < nums.size())
        {
            if (nums[fast] != val)
            {
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;
        }
        return slow;//0~slow现在是不包含val的数
    }
};

2 左右指针刷题

2.1 二分查找

记住模板框架即可。

int binarySearch(vector<int> &nums, int target)
{
	sort(nums.begin(), nums.end());
	int left = 0, right = nums.size() - 1;
	while (left < right)
	{
		int mid = (left + right) / 2;
		if (nums[mid] == target) return mid;
		else if (nums[mid] < target) left = mid + 1;
		else if (nums[mid] > target) right = mid - 1;
	}
	return -1;
}

2.2 两数之和 II - 输入有序数组

在这里插入图片描述

题解

采用二分查找,具体如下方代码所示。

Code

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        //因为数组已经排序好了,所以无需sort
        int left = 0, right = nums.size() - 1;
        int sum = 0;
        vector<int> vec;
        vector<int> res = {-1, -1};
        while (left < right)
        {
            sum = nums[left] + nums[right];
            if (sum == target)
            {
                vec.push_back(left + 1);//下标从1开始,增大下标
                vec.push_back(right + 1);
                return vec;
            }
            if (sum < target)
            {
                ++left;//因为排序好了,小了就移动左指针,大了就移动右指针
            }
            if (sum > target)
            {
                --right;
            }
        }
        return res;
    }
};

结果

在这里插入图片描述

2.3 反转字符串

在这里插入图片描述

题解

直接左右指针边走边进行交换。

Code

class Solution {
public:
    void reverseString(vector<char>& s) {
        int left = 0, right = s.size() - 1;
        while (left < right)
        {
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
        return;
    }
};

结果

在这里插入图片描述

2.4 最长回文子串

在这里插入图片描述

题解

难点在于可以是奇数或者是偶数,找回文串应该是从中心上两边进行扩散。也算是一个算法穷举的思路。

Code

class Solution {
public:
    string longestPalindrome(string s) {
        string res = "";
        for(int i = 0; i < s.length(); i++){
            string s1 = findPalindrome(s, i, i);
            string s2 = findPalindrome(s, i, i+1);
            res = res.length() > s1.length() ? res : s1;
            res = res.length() > s2.length() ? res : s2;
        }
        return res;
    }

    string findPalindrome(string& s, int l, int r){
        while(l >= 0 && r < s.length() && s[l] == s[r]){
            l--;
            r++;
        }

        return s.substr(l+1, r-l-1); // C++中的子串函数substr(pos, count),第二参数count是子串长度,l+1是因为while最后一次判断的时候减去了1,所以得加回来。然后substr中的pos相当于起点,count相当于长度,长度=right - left - 1(减去1是因为最后while判断的时候right+1)
    }
};

结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/800638.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

品牌渠道管理的逻辑

无规矩不成方圆&#xff0c;规则确定了&#xff0c;接下来就是推行这个规则并且执行落地就可以&#xff0c;所以明确问题制定规则就非常重要。这个原则也适用于品牌渠道管理工作&#xff0c;品牌面对经销商低价乱价等问题时&#xff0c;如果仅用打击一种方式去管理&#xff0c;…

Component template should contain exactly one root element

在vue中报错&#xff1a; Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead报错的大致意思是&#xff1a;组件的模板应该只能包含一个根元素&#xff0c;也就是是说作为元素的直…

科技项目验收测试:验证软件产品功能与性能的有效手段

科技项目验收测试是验证软件产品功能与性能的重要手段&#xff0c;在项目开发中起到了至关重要的作用。本文将从产品质量、需求验证、性能测试等方面&#xff0c;探讨科技项目验收测试的有效手段。 1、产品质量保证是验收测试的核心 科技项目验收测试的核心目标是验证软件产品…

DFS()

DFS之连通性模型 dfs 与 bfs都能判断连通性 而且bfs可以得出最短距离 而dfs不可以 dfs 代码比较简洁 迷宫 一天Extense在森林里探险的时候不小心走入了一个迷宫&#xff0c;迷宫可以看成是由 n∗nn∗n 的格点组成&#xff0c;每个格点只有2种状态&#xff0c;.和#&#xff0…

【小尘送书-第三期】Python机器学习:基于PyTorch和Scikit-Learn 》

大家好&#xff0c;我是小尘&#xff0c;欢迎关注&#xff0c;一起交流学习&#xff01;欢迎大家在CSDN后台私信我&#xff01;一起讨论学习&#xff0c;讨论如何找到满意的实习&#xff01; 本文目录 一、前言二、作者简介三、内容简介四、抽奖方式 一、前言 近年来&#xff0…

Vue-resource 实现 get, post请求

Vue-resource是Vue高度集成的第三方包&#xff0c;能很方便的发送请求。 注意Vue-resource依赖于Vue&#xff0c;只能在Vue环境下使用。 导包 //依赖于Vue <script src"./js/vue.js"></script> <script src"./js/elementui.js"></…

ROS与STM32通信-rosserial

文章目录 硬件接线 软件STM32CubeMX配置 rosserial移植上位机订阅-下位机发布上位机订阅下位机发布通信 上位机发布-下位机订阅上位机发布下位机订阅通信 硬件 STM32F103c8t6OLED(I2C)USB2TTLStlink 接线 OLED(GPIO模拟I2C) 硬件引脚OLEDSCLPA4OLEDSDAPA5 USART1 硬件引脚…

SwipeDelMenuLayout失效:Could not find SwipeDelMenuLayout-V1.3.0.jar

一、问题描述 最近在工作上的项目中接触到SwipeDelMenuLayout这个第三方Android开发库&#xff0c;然后我就根据网上的教程进行配置。这里先说一下我的开发环境&#xff1a;Android Studio版本是android-studio-2020.3.1.24-windows&#xff0c;gradle版本是7.0.2。 首先是在se…

LeetCode53.Maximum-Subarray<最大子数组和>

题目&#xff1a; 思路&#xff1a; 这题不会啊...然后发现题解如此简单, 逐层判断.得到最大值. 每次取得当前的最大值.并且更新结果最大值,结果循环扫描后得到结果 代码是&#xff1a; //codeclass Solution { public:int maxSubArray(vector<int>& nums) {int p…

【HarmonyOS】ArkTS自定义组件如何调用通用属性?

【关键词】 ArkTS、通用属性、 BuilderParam 【问题背景】 有个开发者使用ArkTS自定义了一个子组件AnimationButton&#xff0c;里面用到了装饰器 BuilderParam&#xff0c;在父页面中引用的时候使用自定义组件时&#xff0c;使用以下方式调用&#xff1a; 就报了这个错 【问…

基于双 STM32+FPGA 的桌面数控车床控制系统设计

桌 面数控 设 备 对 小 尺寸零件加工在成 本 、 功 耗 和 占 地 面 积等方 面有 着 巨 大 优 势 。 桌 面数控 设 备 大致 有 3 种 实 现 方 案 : 第 一种 为 微 型 机 床搭 配 传统 数控系 统 &#xff0c; 但 是 桌 面数控 设 备 对 成 本 敏感 ; 第二 种 为 基 于 PC…

《TCP IP网络编程》第十一章

第 11 章 进程间通信 11.1 进程间通信的基本概念 通过管道实现进程间通信&#xff1a; 进程间通信&#xff0c;意味着两个不同的进程中可以交换数据。下图是基于管道&#xff08;PIPE&#xff09;的进程间通信的模型&#xff1a; 可以看出&#xff0c;为了完成进程间通信&…

React入门学习笔记1

前言 React是一个用来动态构0建用户界面的JavaScript库&#xff08;只关注于视图&#xff09;。它可以帮助开发人员轻松地创建复杂的交互式界面&#xff0c;以及管理与用户交互的状态。相比于其他的JavaScript框架&#xff0c;React采用了一种不同的编程模型&#xff0c;称为“…

单片机中的通用LED驱动

前言 项目中需要用到很多的LED灯&#xff0c;存在不同的闪烁方式&#xff0c;比如单闪&#xff0c;双闪&#xff0c;快闪&#xff0c;慢闪等等&#xff0c;我需要一个有如下特性的LED驱动 方便的增加不同闪烁模式可以切换闪烁模式增加LED数目不会有太多的改动方便移植&#x…

《焊接点云处理》-V型焊缝处理

焊接点云处理-V型焊缝处理 前言一、代码二、处理步骤前言 处理效果 一、代码 主函数 #include "CGALRECONSTRUCT.h" #include"PCLFUNCTION.h"int main(int argc

vue+leaflet笔记之地图聚合

vueleaflet笔记之地图聚合 文章目录 vueleaflet笔记之地图聚合开发环境代码简介插件简介与安装使用简介 详细源码(Vue3) 本文介绍了Web端使用Leaflet开发库进行地图聚合查询的一种方法 (底图来源:中科星图)&#xff0c;结合Leaflet.markercluster插件能够快速的实现地图聚合查询…

【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动

[导读]本系列博文内容链接如下&#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 在【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值一文中介绍了如何利用…

4.4 if选择结构

4.4 if选择结构 if单选择结构 我们很多时候需要去判断一个东西是否可行&#xff0c;然后我们才去执行&#xff0c;这样的一个过程在程序中用if语句来表示 语法 if(布尔表达式){//如果布尔表达式为true将执行的语句 }if单选择结构流程图 package com.baidu.www.struct;import …

JVM源码剖析之JIT工作流程

版本信息&#xff1a; jdk版本&#xff1a;jdk8u40思想至上 Hotspot中执行引擎分为解释器、JIT及时编译器&#xff0c;上篇文章描述到解释器过度到JIT的条件。JVM源码剖析之达到什么条件进行JIT优化 这篇文章大致讲述JIT的编译过程。在JDK中javac和JIT两部分跟编译原理挂钩&a…

MySQL 服务器的调优策略

点击上方↑“追梦 Java”关注&#xff0c;一起追梦&#xff01; 在工作中&#xff0c;我们发现慢查询一般有2个途径&#xff0c;一个是被动的&#xff0c;一个是主动的。被动的是当业务人员反馈某个查询界面响应的时间特别长&#xff0c;你才去处理。主动的是通过通过分析慢查询…