数组、链表
点击消除
这个题很容易想到用“栈”,但是创建一个stack
最后还要转换成字符串,可以用string
代替栈。
string
的接口很多且实用,常见的接口基本都有:
这个题比较坑的是它说如果字符串为空串则返回0,谁想到返回的是"0"
,我试着返回0
咋都过不去,最后吐了!都怪我太年轻了!
#include <iostream>
using namespace std;
int main()
{
string str, st;
cin >> str;
for (char ch : str)
{
if (!st.empty() && st.back() == ch)
{
st.pop_back();
continue;
}
st.push_back(ch);
}
cout << (st.empty() ? "0" : st);
return 0;
}
环形链表
快慢指针法: 快指针和慢指针初始时指向头节点,当快指针指向和快指针指向节点内的next
指针不为空时,快指针一次走两步,慢指针一次走一步,快指针入环后走N圈后慢指针入环,当快指针和慢指针相等时说明存在环,如果出循环则说明不存在环。
关键的地方是快指针一次走两步,慢指针一次走一步,如果存在环则快指针和慢指针一定会相遇。为什么一定会相遇呢?
如果存在环,假设当慢指针入环时快指针距离此时慢指针的位置为N,则接下来每当快指针追赶慢指针一次,它们的距离就减一,直到减为0,此时快慢指针就相遇了。
bool hasCycle(struct ListNode *head) {
struct ListNode* fast = head, *slow = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return true;
}
}
return false;
}
环形链表 II
还是快慢指针,当快慢指针相遇时我们让meet
指针指向相遇时的节点,然后让头指针head
和meet
指针一步步地向后走,当两指针相遇时指向的节点就是链表开始入环的第一个节点。为什么这两个指针一定会相遇在链表开始入环的第一个节点?
假设头指针距离链表开始入环的第一个节点的长度为L,meet
指针相距链表开始入环的第一个节点的距离是N,环的长度为C,当慢指针入环时快指针走了x圈,因为快指针的速度是慢指针的2倍,那我们可以得到下面的等式:
- 2(L + N) = L + X*C + N
化简得:L = X*C - N,由这个等式可以得出head
和meet
相遇是必然的。
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* fast = head, *slow = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
struct ListNode* meet = fast;
while (head != meet)
{
head = head->next;
meet = meet->next;
}
return meet;
}
}
return NULL;
}
栈、队列
优先级队列
最后一块石头的重量
class Solution {
public:
int lastStoneWeight(vector<int>& stones) {
priority_queue<int> pq;
for (int e : stones) pq.push(e);
while (pq.size() > 1)
{
int x = pq.top();
pq.pop();
int y = pq.top();
pq.pop();
if (x - y > 0) pq.push(x - y);
}
return pq.empty() ? 0 : pq.top();
}
};
数据流中的第 K 大元素
class KthLargest {
priority_queue<int, vector<int>, greater<int>> pq;
int _k;
public:
KthLargest(int k, vector<int>& nums) {
_k = k;
for (int e : nums)
{
pq.push(e);
if (pq.size() > _k) pq.pop();
}
}
int add(int val) {
pq.push(val);
if (pq.size() > _k) pq.pop();
return pq.top();
}
};
前K个高频单词 *
class Solution {
using psi = pair<string, int>;
struct cmp
{
bool operator()(const psi& p1, const psi& p2)
{
if (p1.second == p2.second) return p1.first < p2.first;
return p1.second > p2.second;
}
};
public:
vector<string> topKFrequent(vector<string>& words, int k) {
vector<string> ret(k);
unordered_map<string, int> hash;
for (auto &str : words) hash[str]++;
priority_queue<psi, vector<psi>, cmp> pq;
for (auto &e : hash)
{
pq.push(e);
if (pq.size() > k) pq.pop();
}
while (!pq.empty())
{
ret[--k] = pq.top().first;
pq.pop();
}
return ret;
}
};
数据流的中位数 *
class MedianFinder {
priority_queue<int> left; // 大根堆
priority_queue<int, vector<int>, greater<int>> right; // 小根堆
public:
MedianFinder() {
}
void addNum(int num) {
if (left.size() == right.size())
{
if (left.size() && num <= left.top()) left.push(num);
else
{
right.push(num);
left.push(right.top());
right.pop();
}
}
else
{
if (num >= left.top()) right.push(num);
else
{
left.push(num);
right.push(left.top());
left.pop();
}
}
}
double findMedian() {
if (left.size() == right.size()) return (left.top() + right.top()) / 2.0;
return left.top();
}
};
树
本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~