首页 > 其他分享 >一些Leetcode关于双指针的简单题解

一些Leetcode关于双指针的简单题解

时间:2024-11-17 19:46:00浏览次数:3  
标签:val nums int 题解 元素 数组 Leetcode 指针

26.删除有序数组中的重复项

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。
int removeDuplicates(int* nums, int numsSize) {
    int slow=1;
    for(int fast=1;fast<numsSize;fast++){
        if(nums[fast]!=nums[fast-1]){
            nums[slow++]=nums[fast];
        }
    }
    return slow;
}

非严格递增,即有重复项的递增排列。我们可以设置一快一慢两个指针,快指针向前遍历,直到遇到与上一项不同的值,此时说明 nums [ fast ] 和之前的元素都不同。将 nums [ fast ] 赋给 nums [ slow ] 后慢指针指向下一个位置。因为 nums [ 0 ] 不可能重复以及防止数组下标越界,我们令快慢指针都从下标 1 开始。这样遍历一次后,slow 的值即是 nums 数组的唯一元素数量,返回即可。


27.移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k。
int removeElement(int* nums, int numsSize, int val) {
    int index = 0;
    for(int i = 0;i < numsSize;i++){
        if(nums[i] != val){
            nums[index++]=nums[i];
        }
    }
    return index;
}

与 26.删除有序数组中的重复项 类似,因为移除目标值 val 需要将 val 后的非 val 元素前移,我们可以设置一快一慢两个指针,快指针遍历数组,遇到非 val 的值 nums [ fast ] 则将其赋给 nums [ slow ] 位置后慢指针指向下一个位置;遇到 val 值不进行操作。这样遍历一遍数组后 slow 的值即是 nums 中非 val 的元素数量,返回即可。


283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

void swap(int*a,int*b){
    int temp=*a;
    *a=*b;
    *b=temp;
}
void moveZeroes(int* nums, int numsSize) {
    int slow=0;
    for(int fast=0;fast<numsSize;fast++){
        if(nums[fast]!=0){
            swap(&nums[fast],&nums[slow++]);
        }
    }
}

区分于 27.移除元素,283. 移动零 需要将 0 移动到数组末尾,即交换 0 与 非0 元素,我们可以将本题看作顾全后续数组的 27.移除元素,解题思路与其类似,设置快慢指针,快指针遍历到 非0 元素将其与慢指针下标的数组元素交换,慢指针指向下一个元素,遍历一遍即可。


344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

void reverseString(char* s, int sSize) {
    int left=0,right=sSize-1;
    while(left<right){
        char temp=s[left];
        s[left]=s[right];
        s[right]=temp;
        left++;
        right--;
    }
}

与前三题设置的快慢指针略有不同,本题不允许额外分配数组内存,我们需要设置左右指针令其都向中间移动,并交换两个指针下标分别对应的数组元素,指针移动的结束条件为左指针大于等于右指针,这样可以一并解决数组元素为奇数( left = right )和偶数( left > right )的情况。


844. 比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。

注意:如果对空文本输入退格字符,文本继续为空。

示例 1:
输入:s = “ab#c”, t = “ad#c”
输出:true
解释:s 和 t 都会变成 “ac”。

示例 2:
输入:s = “ab##”, t = “c#d#”
输出:true
解释:s 和 t 都会变成 “”。

示例 3:
输入:s = “a#c”, t = “b”
输出:false
解释:s 会变成 “c”,但 t 仍然是 “b”。

bool backspaceCompare(char* s, char* t) {
    char sTure[200],tTure[200];
    int nS=strlen(s),nT=strlen(t);
    int topS=-1,topT=-1;
    for(int i=0;i<nS;i++){
        if(s[i]!='#'){
            sTure[++topS]=s[i];
        }
        else if(topS>=0){
            sTure[topS]=0;
            topS--;
        }
    }
    for(int i=0;i<nT;i++){
        if(t[i]!='#'){
            tTure[++topT]=t[i];
        }
        else if(topT>=0){
            tTure[topT]=0;
            topT--;
        }
    }
    return strcmp(sTure,tTure)==0;
}

本题解选择了使用栈来解决。定义两个真数组(退格后比较的)和栈顶( -1 )。小写字母和井号可以分别表示成栈的入栈 push 和出栈 pop 操作,这样思路就很清晰了:遍历数组,遇到 非# 则压入栈中( 赋值后栈顶++ );遇到 # 则令栈顶元素出栈(赋 \0 给栈顶元素后栈顶-- )。值得一提的是 退格操作( # 出栈 )的数量可能大于其前面 入栈操作 数量,我们需要给栈顶设置最小值 -1 ,避免发生数组下标越界的未定义行为。
通过遍历两个数组得到两个真数组后,返回真数组比较的结果,这里直接使用了字符串函数 strcmp 来比较,返回 0 则说明两者相等。

标签:val,nums,int,题解,元素,数组,Leetcode,指针
From: https://blog.csdn.net/2401_87853595/article/details/143833350

相关文章

  • Leetcode141-环形链表
    思路链表判环方法:快慢指针法其实没那么高级,很简单的理解就是,采用两个指针,一个每次走两步,一个每次走一步,如果链表有环,那么每次走两步的指针,也就是走得快的指针一定会追上走得慢指针。代码第一种写法://写法1publicclassSolution{publicbooleanhasCycle(ListN......
  • [题解]AtCoder Beginner Contest 380(ABC380) A~F
    A-123233照题意统计即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;strings;map<char,int>ma;signedmain(){ cin>>s; for(chari:s)ma[i]++; if(ma['1']==1&&ma['2']==2&&ma['3']==3)co......
  • 指针特殊类型·补充篇
    个人总结,有错误你懂的。             熬过一切,就一切都过往云烟了吧。目录:函数指针指的是存放函数地址的指针,也就是指向函数地址的指针。void(*S)(int*x,int*y)就是一个函数指针,这说明函数名也可以当函数首地址用,和数组相似。函数指针还可用作回......
  • 学习日记---第4天(0基础 3min 指针快速入门)
    笔记复习1.函数声明11语法:函数返回值类型函数名参数列表作用:告诉编译器在这个地方已经定义了函数,这样编译器可以在这个定义的后面调用函数,即使函数的定义在调用之后(具体的函数定义还是要写的)ps:函数的声明可以有多个,但函数的实现只能有一个示例:利用函数实现连两个数的和......
  • 【星航计划】2024.11 Div. 3 题解
    2024--星航计划--十一月份--基础算法A.分段每一段连续的\(1\)之间是独立的,我们只需要关心一段连续的1的结果。可以证明对于一段连续的\(1\),最优策略是将其划分成多个单独的\(1\)以及可能余下的连续两个\(1\)。对于\(k\)个连续的\(1\),如果\(k\)是奇数,......
  • 【学校训练记录】11月个人训练赛4个人题解
    A题意可以理解为在a,b的范围内如果一个数是某个整数的立方,求与其距离为k的范围内有几个整数的平方数,我们可以对于每个立方数求出其数量,注意边界问题#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;inta,b,k;voidsolve(){ cin>>a>>b>>k; in......
  • 102. 二叉树的层序遍历【 力扣(LeetCode) 】
    文章目录零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码零、原题链接102.二叉树的层序遍历一、题目描述给你二叉树的根节点root,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。二、测试用例示例1:输入:root=[3,9,20,null,nul......
  • 【未完结】 AtCoder Beginner Contest 380 题解
    AtCoderBeginnerContest380Rated:\(770\)A-123233简单模拟B-HurdleParsing字符串模拟C-MoveSegment找到第\(k\)个块的下标,模拟。D-StrangeMirroringE-1DBucketToolF-ExchangeGameG-AnotherShuffleWindow......
  • CF603E Pastoral Oddities 题解
    Description给定一张\(n\)个点的无向图,初始没有边。依次加入\(m\)条带权的边,每次加入后询问是否存在一个边集,满足每个点的度数均为奇数。若存在,则还需要最小化边集中的最大边权。\(n\le10^5\),\(m\le3\times10^5\)。Solution考虑给定一个图,怎么判断这个图存在一个......
  • 看过这个,你可能更了解指针3
    我们来看下图运算的结果会是什么呢?接下来开始我们的分析。****在1中arr被单独放在strlen函数中,表示数组的首元素地址。由于数组中没有\0,因此strlen在计算arr长度的时候并不会出现正常结果,但是也不至于造成死循环。因为在arr后的空间中往往会存在0等元素存放在地址中,这里......