首页 > 其他分享 >1月20日 刷题随笔1 双指针1

1月20日 刷题随笔1 双指针1

时间:2024-01-20 17:47:32浏览次数:39  
标签:size 20 nums int 元素 ++ 数组 随笔 刷题

1.反转字符(力扣344)

https://leetcode.cn/problems/reverse-string/description/

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题

利用i,j两个指针,i指向数组开头,j指向数组末尾,然后i不断往后走,与此同时j往前走,每移动一次位置,s[i]与s[j]就交换位置,直到i等于s.size()/2-1,即完成反转
代码如下:

点击查看代码
class Solution {
public:
    void reverseString(vector<char>& s) {
    int j = s.size() - 1;
    for(int i = 0; i < s.size() / 2 ; i ++){
        swap(s[i], s[j]);
        j --;
    }
    }
};

2.移除元素(力扣27)

https://leetcode.cn/problems/remove-element/description/

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

对于样例:
输入:nums = [3,2,3,5,3], val = 3
输出:2, nums = [2,5]
数组3,2,3,5,3 对应的下标依次是0,1,2,3 而现在我们需要将3都删除,那么2的下标应该变为0,5的下标变为1,该过程的实现我们需要遍历数组,所以我们需要用到一个指针i,但是如何将与val相等的值删掉然后让数组的下标不变呢?那么就需要用到第二个指针j,如果遍历到的nums[i]等于val,j指针就不动,直到i指针指向的数不为val再将j指针指向的位置赋值为此时i指针的值,赋值结束后j指针加1,便实现了,元素的移除。总而言之,就是相等的跳过,不相等的依次赋值。
代码如下:

点击查看代码
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int j = 0;
        for(int i = 0; i < nums.size(); i ++){
            if(nums[i] != val){
                nums[j ++] = nums[i];
            }
        }
        return j;
    }
};

3.删除有序数组中的重复项(力扣26)

https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

此道题和上述题目类似,我们先来看样例
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
我的思路:可以用一个数组hash来记录nums数组中各个元素出现的次数,有i和j两个指针,如果hash[nums[i]]>0,那么说明该元素已经出现过了,j指针不动,i指针继续滑动,直到滑动到hash[nums[i]]=0时,将其赋值给j,然后j++,最后再返回j的值即可,但是不能出现新数组,我们只能在原数组做修改,所以做判断时也只能在原数组做。
于是,同样的,我们需要i和j两个指针,j指针用来保留当前元素,以样例1为例,最开始i与j都指向nums[0]即1,然后,i指针向后移动一个位置,nums[i]此时为nums[1],判断nums[1]与nums[j]即nums[0]是否相等,此时是相等的,我们不需要做额外的操作,只需将i指针往后移动,nums[i]此时为2,再与nums[j]即nums[0]作比较,不相等,那么就将此时的nums[i]的值赋给此时的nums[j]的下一个位置,即nums[++j],按照这个逻辑依次作判断,最后便可的删除所有重复元素啦,最后返回j+1,因为此时的j是下标
代码如下:

点击查看代码
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
    int j = 0;
    for(int i = 0; i < nums.size(); i ++){
        if(nums[j] != nums[i]){
            nums[++j] = nums[i];
        }
    }
    return j + 1;
    }
};

4.移动零(力扣283)

https://leetcode.cn/problems/move-zeroes/description/

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。

和2类似,即2中的val固定为0,相等跳过,不等赋值,不过最后还要将剩余的位置全部补为0

代码如下:

点击查看代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
    int j = 0;
    for(int i = 0; i < nums.size(); i++){
        if(nums[i] != 0){
            nums[j ++] = nums[i];
        }
    }
    for(int i = j; i < nums.size(); i++){
        nums[i] = 0;
    }
    }
};

当然这道题还可以有另一种解法,即将整个数组一分为二,左边为不为0的数,右边为是0的数,这里的分界线就是0本身,与快速排序的思想类似
代码如下:

点击查看代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
    int j = 0;
    for(int i = 0; i < nums.size(); i ++){
        if(nums[i] != 0){
            swap(nums[i], nums[j]);
            j ++;
        }
    }
    }
};

5.比较含退格的字符串(力扣844)

https://leetcode.cn/problems/backspace-string-compare/description/

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

这道题用字符串模拟栈就很好解,关于匹配的就可以考虑用栈的思想,即将输入的字符串重新依次赋值给一个新的字符串,如果遇到退格符,就将新字符串的末尾字符删去,代码如下:

点击查看代码
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        string ss, tt;
        for(int i = 0; i < s.size(); i ++){
           if(s[i] != '#'){
               ss += s[i];
           }
           else if(!ss.empty()) ss.pop_back();
        }
        for(int i = 0; i < t.size(); i ++){
           if(t[i] != '#'){
               tt += t[i];
           }
           else if(!tt.empty()) tt.pop_back();
        }
        if(ss != tt) return false;
        else return true;
    }
};

运用此解法踩的坑:一定要判断新字符串是否为空,如果没有这个判断就会运行错误。在string类中,删除末尾元素的函数即为pop_back()。

当然,这道题也可以用双指针来解,感觉这道题用双指针不是很好想,需要从后往前遍历,通过统计‘#’的数量然后用跳过元素的方法模拟删除操作然后逐一比较
代码如下:

点击查看代码
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int s_num = 0;//记录s的‘#’个数
        int t_num = 0;//记录t的‘#’个数
        int i = s.size() - 1;
        int j = t.size() - 1;
        while(1)
        {
        while(i >= 0){
            if(s[i] == '#') s_num ++;
            else{
                //如果当前还有空格符,空格符数量减一
                if(s_num > 0) s_num --;
                //如果没有了,就退出循环进行比较
                else break;
            }
            //跳过该元素表示删除
            i --;
        }
        //t与s同理
        while(j >= 0){
            if(t[j] == '#') t_num ++;
            else{
                if(t_num > 0) t_num --;
                else break;
            }
            j --;
        }
        //首先判断s与t是否有遍历到头的,如果二者有一个遍历到头的,就退出循环
        if(i < 0 || j < 0) break;
        //都没有遍历到头就比较当前的字符,如果不相等,就直接返回假
        if(s[i] != t[j]) return false;
        //比较完以后记得两个字符串都向前挪一个位置
        i--;j--;//这一步很重要!!!!
        }
        //如果二者同时遍历到头,则说明相等
        if(i < 0 && j < 0) return true;
        //否则,为假
        else return false;
    }
};

6.替换数字

https://kamacoder.com/problempage.php?pid=1064

给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。

首先统计该字符串中含有多少个数字,记为count,然后将该字符串扩展为count*5+原长度,运用resize函数进行扩展,然后再从后往前遍历字符串,如果该字符为数字,则倒序将number存入字符串中
其实很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:

  • 不用申请新数组。
  • 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。

代码如下:

点击查看代码
# include<iostream>
# include<algorithm>
using namespace std;
# include<string>
const int N = 10010;
 
int main(){
    string s;
    cin >> s;
    int count = 0;
    int sOldsize = s.size();
    for(int i = 0; i < s.size(); i++ ){
        if(s[i] <= '9' && s[i] >= '0'){
            count++;
        }
    }
    s.resize(s.size() + count * 5);
    int sNewsize = s.size();
    int j = sNewsize - 1;
     
    for(int i = sOldsize - 1; i >= 0; i--){
        if(s[i] <= '9' && s[i] >= '0'){
            s[j] = 'r';
            s[j - 1] = 'e';
            s[j - 2] = 'b';
            s[j - 3] = 'm';
            s[j - 4] = 'u';
            s[j - 5] = 'n';
            j = j - 5;
        }
        else {
            s[j] = s[i];
        }
        j--;
    }
    cout << s;
    return 0;
}

标签:size,20,nums,int,元素,++,数组,随笔,刷题
From: https://www.cnblogs.com/mjiujiu/p/17976818

相关文章

  • NOIP2021
    NOIP2021来啦!Day0为了方便,我们提前一天便到了考点附近。出发之前,我们又在机房里呆了两个小时,大家都在忙着复习着诸如线段树等模板。两个小时的车程后,我们吃过饭,老师又把我们集中开会,跟我们讲了一堆注意事项。讲完之后,大家都睡了。Day1第一次打联赛,不免有些小紧张,毕竟这些题目......
  • P8112 [Cnoi2021] 符文破译 题解
    题目传送门思路先看数据范围,我们发现两个字符串的长度最大会达到\(5\times10^7\)。这立刻打消了我用暴力的想法。于是,我选择了用KMP模式匹配,这一个能够在线性时间内判定字符串\(A\)是否是字符串\(B\)的字串,并求出字符串\(A\)在字符串\(B\)中各次出现的位置。如......
  • AT_codefestival_2016_final_b
    根据题意,很容易得知要使得它们的最大值最小,就要从最小的\(1\)开始用。转化一下题意,不难发现,我们只需求出最小的\(k\),使得\[\\sum_{i=1}^ki\\gen\]于是思路便产生了:对\(1\),\(2\),\(3\),⋯\(k\)求和,直到上述式子成立。可以很容易地看出来一个规律:\[(\\sum_{i=1}^ki\)......
  • Ubuntu20.04部署docker环境
    1.卸载旧的docker版本forpkgindocker.iodocker-docdocker-composepodman-dockercontainerdrunc;doapt-getremove$pkg;done2.切换国内的软件源cat>/etc/apt/sources.list<<EOFdebhttps://mirrors.aliyun.com/ubuntu/focalmainrestricteduniversemultiv......
  • Check for balanced parentheses using stack【1月20日学习笔记】
    点击查看代码//Checkforbalancedparenthesesusingstack#include<iostream>#include<stack>//stackfromstandardtemplatelibrary(STL)#include<string>usingnamespacestd;boolarepair(charopening,charclosing){ if(opening=='(&#......
  • 昆虫科学院 AtCoder Race Ranking 2023 Autumn
    概况为提高选手们的训练/比赛热情,我们(昆虫科学院)通过商讨,在\(2023-5-25\)仿照AtCoderRaceRanking(WTF)机制,设立了“昆虫科学院AtCoderRaceRanking2023”。该排行榜为\(2023\sim2024\)赛季的第二轮排行。校内参赛选手(按照学号排序)AtCoder用户名学号......
  • CPU跑分工具:SPEC2006
    一.工具介绍前言SPEC2006benchmark是SPEC新一代的行业标准化的CPU测试基准套件。重点测试系统的处理器,内存子系统和编译器。这个基准测试套件包括的SPECint基准和SPECfp基准。主要依赖于gcc,g++,gfortran并与其版本息息相关。其中SPECint2006基准包含12个不同的基准测试和SP......
  • 1.20学习进度
    1.standaloneHA的运行原理:为解决单点故障问题,spark由两种方案:基于文件系统的单点恢复(只能用于开发或测试环境)、基于zookeeper的standbymaster(可以用于生产环境);基于zookeeper做状态的维护,开启多个master进程,一个作为活跃,其他的作为备份,当活跃进程宕机,备份master进行接管第五章1.......
  • Windows 10 version 22H2 (updated Jan 2024) 中文版、英文版下载
    Windows10version22H2(updatedJan2024)中文版、英文版下载Windows1022H2企业版arm64x64作者主页:sysin.orgWindows10更新历史记录Windows10,version22H2,alleditions发布日期:2022/10/18版本:Windows10,版本22H2Windows10版本信息2022/10/19从W......
  • Windows 11 version 23H2 中文版、英文版 (x64、ARM64) 下载 (updated Jan 2024)
    Windows11version23H2中文版、英文版(x64、ARM64)下载(updatedJan2024)Windows11,version23H2,2024年1月更新作者主页:sysin.orgWindows11目前版本所有的日期都按照ISO8601格式列出:YYYY-MM-DD)服务频道版本服务选项上市日期最后修订日期最新版本......