第一题:数字统计
拿到这个题目首先的思路就是输入L和R作为左右边界,然后通过for循环遍历[L, R]之间的值,并且将每一个值都拷贝一份进行数据拆分操作
如何数据拆分呢?数据拆分就是两步:1)用10取模,取模能取到个位数;2)除10,能干掉个位数。
代码示例:
#include <iostream>
using namespace std;
int main()
{
int L, R;
cin >> L >> R;
int ret = 0;
// 遍历范围[L, R]的所有整数
for(int i = L; i <= R; ++i)
{
int tmp = i;
// 对每个数做拆分
while(tmp)
{
if(tmp % 10 == 2) ret++;
tmp /= 10;
}
}
cout << ret;
}
第二题:两个数组的交集
从一个数组中的元素是否存在于另一个数组中这样的一一映射问题我们首先要想到的就是哈希。
首先先将nums1放入到哈希中,再遍历nums2中的每一个元素,如果这个元素在哈希中存在,则我们将这个元素插入到要返回的数组ret中。
细节问题:1)我们是要用unordered_map
呢?还是数组的下标映射呢?仔细审题,由于我们的数组长度是0~1000不是特别大,我们就用数组下标映射。2)万一我们的nums2中有两个元素在哈希中都能找到怎么办呢?很简单,只要想到第一个元素映射之后,哈希表就将这个元素“删掉”就可以了!这里的删掉对于哈希而言只是一种标记(如有true变为false,由1变为0)
#include <vector>
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int> result;
bool hash[1010] = {0};
// 将nums1的元素添加到hash中
for(auto& ch1 : nums1)
{
hash[ch1] = true;
}
// 遍历nums2,和hash比较
for(auto& ch2 : nums2)
{
// ch2在hash中存在
if(hash[ch2] == true)
{
result.push_back(ch2);
hash[ch2] = false;
}
}
return result;
}
};
时间空间复杂度分析
时间复杂度:O(N)。因为要遍历数组nums1和nums2,所以时间复杂度为O(N)
空间复杂度:O(N)。因为要建立hash将nums1对应下标中的元素置为true,所以空间复杂度为O(N)
第三题:点击消除
这题的思想类似于我们之前做的括号匹配。
通过栈的后进先出,如果我在数组遍历的过程中遇到和栈顶元素相同的就出栈,因为相同时,栈顶元素和数组里的元素是相邻的,这就达到了连续相同的两个字符消除的目的。
以下是具体实现步骤:
注意细节:最后依次从栈顶取出元素插入到新的string容器中,别忘了还要逆序哦!
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
int main() {
stack<char> st;
string str;
cin >> str;
int begin = 0;
while(str[begin] != '\0')
{
// 刚开始栈为空,插入str的第一个元素
if(st.empty())
{
st.push(str[begin++]);
// begin++之后一定要判断一下,判断begin是否到了str的末尾
if(str[begin] == '\0') break;
}
// 取栈顶元素去和str元素比较
char tmp = st.top();
if(str[begin] != tmp) // 不相等就插入
{
st.push(str[begin++]);
if(str[begin] == '\0') break;
}
else // 相等就出栈
{
st.pop();
begin++;
if(str[begin] == '\0') break;
}
}
// 栈为空
if(st.empty()) cout << 0;
// 栈不为空
string ret;
while(!st.empty())
{
char top = st.top();
ret.push_back(top);
st.pop();
}
reverse(ret.begin(), ret.end());
cout << ret;
}
我们也可以不关系string容器如何遍历,直接运用范围for(底层封装了迭代器),我们不需要控制循环结束条件,因为STL已经帮我们封装好了。
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
int main() {
stack<char> st;
string str;
cin >> str;
for(auto& ch : str)
{
// 刚开始栈为空,插入str的第一个元素
if(st.empty())
{
st.push(ch);
continue;
}
// 取栈顶元素去和str元素比较
char tmp = st.top();
// 不相等就插入
if(ch != tmp) st.push(ch);
// 相等就出栈
else st.pop();
}
// 栈为空
if(st.empty()) cout << 0;
// 栈不为空
string ret;
while(!st.empty())
{
char top = st.top();
ret.push_back(top);
st.pop();
}
reverse(ret.begin(), ret.end());
cout << ret;
}
当然这题还有第二种解法:运用数组去模拟栈,这样最后就不用逆序了
int main() {
// 数组st模拟栈
string str, st;
cin >> str;
for(auto& ch : str)
{
if(st.size() != 0 && st.back() == ch) st.pop_back();
else st += ch;
}
cout << (st.size() == 0 ? "0" : st) << endl;
}
时间空间复杂度分析
时间复杂度:O(N)。因为要遍历数组,所以时间复杂度为O(N)
空间复杂度:O(N)。因为要建立栈存储数组中的元素,所以空间复杂度为O(N)