观前提醒:
笔试所有系列文章均是记录本人的笔试题思路与代码,从中得到的启发和从别人题解的学习到的地方,所以关于题目的解答,只是以本人能读懂为目标,如果大家觉得看不懂,那是正常的。如果对本文的某些知识有不同的观点,欢迎讨论。
题目链接:
第二题:两个数组的交集_牛客题霸_牛客网
第三题:点击消除_牛客题霸_牛客网
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第一题
思路:
本题要求统计“2”的数量,给出了一个数据范围。
很明显,最简单的想法是,
1)遍历每一个数,然后统计每个数的“2”的个数,再相加。
那么第二个考虑的问题是,怎么统计每个数的“2”的个数。
这里的思路是遍历的每个数字的每一位,如何遍历呢。
2)两种办法,一、将数字num%10就可以得出每一位,二、将数字转变为字符串,然后遍历字符串就好。
第一题 代码:
#方法一,取模遍历
#include <iostream>
using namespace std;
int main() {
int a=0,b=0;
scanf("%d %d",&a,&b);
int count=0; //负责统计二的个数
for(int i=a;i<=b;i++)
{
int y=i;//不要直接使用i会导致循环出现问题
while(y != 0)
{
int x=y%10; //记录下i的每个位置上的数字
if(x == 2) count++;
y/=10;
}
}
printf("%d\n",count);
return 0;
}
#方法二,字符遍历
#include <iostream>
#include <string>
using namespace std;
int main() {
int a=0,b=0;
scanf("%d %d",&a,&b);
string str;
int count=0;
for(int i=a;i<=b;i++)
{
str=to_string(i);
for(int j=0;j<str.size();j++)
{
if(str[j] == '2') count++;
}
}
printf("%d\n",count);
return 0;
}
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第二题
思路
本题要求求两个数组的公共部分
脑子的第一想法是,将两个数组遍历一边,但是这也导致了另一个问题,如果数组中有重复元素该怎么办。
例如下图所示
如果是按照,只遍历一边的想法,很有可能我们的最终结果是[2,2]。但是牛客的要求是【2】说明我们要去重。
1)对原先的两个数组去重
可如何去重呢?也很简单使用我们的数据结构---哈希表不就好了吗。是使用自带去重功能的set还是map都可以,不过这道题的取值范围比较小,我们可以通过数组模拟哈希。
2)使用数据结构的哈希,或者是使用数组模拟
第二题 代码 :
#使用STL的set去重
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int> s1, s2;
vector<int> ret;
for(auto& e:nums1)
s1.insert(e);
for(auto& e:nums2)
s2.insert(e);
//遍历元素较少的set,提高效率
if(s1.size() <s2.size())
{
for(auto& e:s1)
{
if(s2.count(e))
{
ret.push_back(e);
}
}
}
else
{
for(auto& e:s2)
{
if(s1.count(e))
{
ret.push_back(e);
}
}
}
return ret;
}
};
class Solution {
//这里一定要初始化,牛客的数组初始化与力扣的初始化不一样,你不初始化,它默认是随机值。
bool hash[1001]={false};
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int> ret;
for(auto& e:nums1)
{
hash[e]=true;
}
for(int i=0;i<nums2.size();i++)
{
if(hash[nums2[i]])
{
ret.push_back(nums2[i]);
hash[nums2[i]]=false;//这一步就是相对于去重了,一个数字只使用一次。
}
}
return ret;
}
};
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第三题
思路
我们模拟一遍这种消除字符串的行为,第一次外面来了个“a”,由于字符串为空,不会消除,字符进入字符串中,第二次来了个“b”没影响,第三次来了个“b”,但是这次我们字符串未是一个“b”(不是a了),所以b消除了。我们回顾这个过程发现这个过程是不是与我们的栈十分相似,我们不就可以使用栈了模拟这个数据结构吗?
1)使用栈模拟这个过程
同时我们发现这个过程只是需要后进先出的特性,所以我们也可以选择使用数组去模拟数组,来完成这个过程。使用栈模拟后,消除的结果存放在栈中,我们需要做的是将栈的元素导出。
2)遍历栈,构建一个新的返回值
第三题 代码
#include <iostream>
#include <string>
#include<vector>
using namespace std;
int main() {
string str="";
cin>>str;
int n=str.size();
vector<char> sc;
for(int i=0;i<n;i++)
{
if(sc.empty()) //数组为空,肯定不能匹配,直接进入
{
sc.push_back(str[i]);
}
else if(sc.back() == str[i])
{
sc.pop_back();
}
else {
sc.push_back(str[i]);
}
}
str.clear();
for(auto& e:sc) str+=e;
if(str.size())
printf("%s\n",str.c_str());
else
{
printf("0\n");
}
return 0;
}