【C++】 —— 笔试刷题day_12

一、删除公共字符

题目解析

题目给了两个字符串(其中包含空格),让我们在第一个字符串中删除第二个字符串中的字符。

我们要输出删除后的字符串。

算法思路

这道题,如果直接按照题目中的要求去第一个字符串中删除字符,那还是有一点难度的。

我们通过观察题目可以发现,第二个字符串str2中的所有字符,我们都要在str1中删除;

那我们不妨记录一下str2中出现的字符 ,这样再遍历str1,再将str2中出现的字符进行删除;

这里还可以进行一下优化:我们知道在一个字符串中删除一个字符,代价是很大的 ,所以我们重新定义一个字符串ret,如果str1中字符在str2中没有出现,就放到ret中去。

大致思路就如上所示,现在来梳理一下整个过程

遍历str2记录其中所有的字符: 首先要记录str2中出现的所有字符,这里定义一个数组即可(大小200左右应该就够用);

遍历str1,将str2中没有出现的字符放到新的字符串中: 这里也可以不定义新的字符串,直接输出字符即可。

代码实现

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

int main() {
    string s,t;
    getline(cin,s);
    getline(cin,t);
    bool hash[200] ={false};
    for(auto& e:t)
    {
        hash[e] = true;
    }
    string ret;
    for(auto& e:s)
    {
        if(hash[e] == false)
            ret+=e;
    }
    cout<<ret<<endl;
    return 0;
}

二、两个链表的第一个公共结点

题目解析

这两道题可以说老朋友了,在之前初学链表时,就做过这道题了;

题目还是给了两个链表,让我们找出来它们相交的第一个节点并返回;如果不相交就返回nullptr

算法思路

对于这道题,先来看思路一(也是之前做这道题的思路)

分别遍历两个链表,记录分别有多少个节点;

让指向长链表的指针先走(两个链表节点数的差值x步。

然后再同时遍历,直到两个指针相等(如果链表不相交,两个链表遍历到nullptr

返回当前两个指针相等的位置即可。

这里就不过多叙述了,现在来看思路二:

它们给了两个链表,我们将这两个链表分为以下三个部分

观察上图,我们可以得到一个等式关系:x1 + x + x2 = x2 + x + x1。(看到这,这不肯定相等吗,就换了一个位置)

那我们如果这样来理解呢:

  • 我们让cur1先遍历x1 + x的部分 ,遍历完后再让cur1去遍历x2部分。
  • 同时让cur2遍历x2 + x的部分 ,遍历完后再让cur2去遍历x1部分。
  • 因为x1 + x + x2 = x2 + x + x1,所以我们cur1cur2会同时遍历到两个链表相交的第一个节点的位置。

那如果两个链表不相交怎么办?

这个就很好说了,没有相交部分x = 0,那cur1cur2就会同时遍历到nullptr位置,最后返回即可。

代码实现

cpp 复制代码
class Solution {
  public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        ListNode* cur1 = pHead1;
        ListNode* cur2 = pHead2;
        while (cur1 != cur2) {
            cur1 = cur1 == nullptr ? pHead2 : cur1->next;
            cur2 = cur2 == nullptr ? pHead1 : cur2->next;
        }
        return cur1;
    }
};

三、mari和shiny

题目解析

题目给了一个字符串,让我们找出这个字符串中一个有多少个shy子序列

这里要注意,是子序列而不是子数组,这里子序列可以是不连续的;

通过示例一也可以看出来。

算法思路

这道题让我们找出shy子序列,虽然说是不连续的,但是shy相对位置是固定的;(也就是说hsyyhs这些是不算shy子序列的)

首先来看我们这道题暴力解法:

遍历字符串,遇到s就在s后面找hy

hy是,遍历到h再在后面找y

这要通过多层循环,可以说非常麻烦的。

现在来进行一下优化:

我们要找shy,那就要先找到sh;找sh就要先找到s;(这里我们定义数组s,h,y

  • s[i]:表示区间[0,i]s的数量。
  • h[i]:表示区间[0,i]sh的数量。
  • y[i]:表示区间[0,i]shy的数量

现在我们来尝试去推到一下状态转移方程。

如果i位置是s,那**s[i] = s[i-1]+1;否则s[i] = s[i-1]。**

如果i位置是h,那区间[0,i]sh就可以分成两部分(一部分在区间[0,i-1]中的sh,另一部分就是区间[0,i-1]中的si位置的h组成的sh)那我们的**h[i] = h[i-1] + s[i-1]否则h[i] = h[i-1] i位置不是h**)。

如果i位置是y,那区间[0,i]中的shy就可以分为两部分(一部分是区间[0,i-1]中的shy,另一部分是区间[0,i-1]中的shi位置的y组成的shy)那我们的**y[i] = y[i-1] + h[i-1];否则y[i] = y[i-1] i位置不是y**)。

状态转移方程如上,现在来进行一下优化:

如果我们真的创建三个dps,h,y;那未免一些太浪费空间了,我们可以使用三个变量来代替s,h,y

  • 遍历字符串str
  • 遇到ss++;(表示区间[0,i]s的数量)
  • 遇到hh+=s(表示区间[0,i]sh的数量)
  • 遇到yy+=h(表示区间[0,i]shy的数量)

最后我们输出y即可。

代码实现

这里要注意数据的范围,1 <= n <= 300000 ,我们如果使用int来计数会超出范围的,要是有long long

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;

int main()
{
    int n;
    string str;
    cin>>n>>str;
    long long s = 0,h = 0,y = 0;
    for(int i=0;i<n;i++)
    {
        if(str[i] == 's')    s++;
        else if(str[i] == 'h')    h+=s;
        else if(str[i] == 'y')    y+=h;
    }
    cout<<y<<endl;
    return 0;
}

到这里本篇博客就结束了,感谢支持
继续加油哇!!!

相关推荐
佚名涙20 分钟前
go中锁的入门到进阶使用
开发语言·后端·golang
猫猫的小茶馆21 分钟前
【PCB工艺】软件是如何控制硬件的发展过程
开发语言·stm32·单片机·嵌入式硬件·mcu·51单片机·pcb工艺
勘察加熊人1 小时前
wpf+c#路径迷宫鼠标绘制
开发语言·c#·wpf
小黄人软件2 小时前
C# ini文件全自动界面配置:打开界面时读ini配置到界面各控件,界面上的控件根据ini文件内容自动生成,点保存时把界面各控件的值写到ini里。
开发语言·c#
二进制人工智能3 小时前
【QT5 网络编程示例】TCP 通信
网络·c++·qt·tcp/ip
Android洋芋5 小时前
C语言深度解析:从零到系统级开发的完整指南
c语言·开发语言·stm32·条件语句·循环语句·结构体与联合体·指针基础
bjxiaxueliang5 小时前
一文详解QT环境搭建:Windows使用CLion配置QT开发环境
开发语言·windows·qt
莫有杯子的龙潭峡谷5 小时前
3.31 代码随想录第三十一天打卡
c++·算法
Run_Teenage6 小时前
C语言 【初始指针】【指针一】
c语言·开发语言
苹果.Python.八宝粥6 小时前
Python第七章02:文件读取的练习
开发语言·python