记录LeetCode算法讲解经典版,涉及相关数据结构和算法的经典题目及相关题目解题思想和代码实现。
目录
一、预备知识
- 栈是先进后出的线性表,队列是先进先出的线性表。
- c++STL中封存了栈的数据结构stack,其中是stack的相关操作。
- c++STL中封存了栈的数据结构queue,其中是queue的相关操作。
- 二叉堆:父节点始终比子节点大的完全二叉树。
- c++STL中优先队列封存了二叉堆。
二、例题
例1、使用队列实现栈(easy)(栈、队列)
- 解题思路:申请一个临时队列,在新元素进入原始队列之前,将原始队列里的元素依次压入临时队列,新元素进入原始队列,再将临时队列里元素依次压入原始队列。
- 代码实现
#include<stdio.h>
#include<queue>
using namespace std;
class MyStack {
private:
queue<int> data;
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
/*定义临时队列*/
queue<int> temp_data;
/*原始队列元素依次进入临时队列*/
while(!data.empty()){
int temp=data.front();
data.pop();
temp_data.push(temp);
}
/*新元素进入*/
data.push(x);
/*临时队列元素再依次进入原始队列*/
while(!temp_data.empty()){
int temp = temp_data.front();
temp_data.pop();
data.push(temp);
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int temp = data.front();
data.pop();
return temp;
}
/** Get the top element. */
int top() {
return data.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return data.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
例2、使用栈实现队列(easy)(栈、队列)
- 解题思路:同上。
- 代码实现:
#include<stack>
using namespace std;
class MyQueue {
private:
stack<int> data;
public:
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
stack<int> temp_data;
while(!data.empty()){
int temp = data.top();
data.pop();
temp_data.push(temp);
}
data.push(x);
while(!temp_data.empty()){
int temp = temp_data.top();
temp_data.pop();
data.push(temp);
}
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
int temp = data.top();
data.pop();
return temp;
}
/** Get the front element. */
int peek() {
return data.top();
}
/** Returns whether the queue is empty. */
bool empty() {
return data.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
例3、包含min函数的栈(easy)(栈)
- 解题思路:1个变量无法记录栈中所有状态下的最小值,栈中每个状态,都要一个变量记录最小值,即用另一个栈,存储各个状态下的最小值。
- 代码实现:
#include<stack>
using namespace std;
class MinStack {
private:
/*数据栈*/
stack<int> data;
/*最小值栈*/
stack<int> data_min;
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
data.push(x);
if(data_min.empty()){
data_min.push(x);
}
else{
if(x<data_min.top()){
data_min.push(x);
}else{
data_min.push(data_min.top());
}
}
}
void pop() {
data.pop();
data_min.pop();
}
int top() {
return data.top();
}
int getMin() {
return data_min.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
例4、合法的出栈序列(medium)(栈、队列)
- 题目描述:
- 解题思路:使用栈和队列模拟输入输出。
例子:
- 代码实现:
#include<stdio.h>
#include<stack>
#include<queue>
using namespace std;
bool ok(queue<int> &que){
stack<int> sta;
int length = que.size();
for(int i =1;i<=length;i++){
sta.push(i);
while(!sta.empty()&&que.front()==sta.top()){
sta.pop();
que.pop();
}
}
if(!que.empty()){
return false;
}
return true;
}
int main(){
int p=0;
queue<int> que;
int n;
int m;
while(scanf("%d",&n)==1){
if(n==0){
break;
}
if (p) printf("\n");
p++;
while(true){
scanf("%d",&m);
if(m==0){
break;
}else{
que.push(m);
}
for(int i=1;i<n;i++){
scanf("%d",&m);
que.push(m);
}
//判断是否可以序列化
if(ok(que)){
printf("Yes\n");
}else{
printf("No\n");
}
//清空队列
while(!que.empty()){
que.pop();
}
}
}
return 0;
}
例5、数组中第K大的数(easy)(堆)
- 题目描述:
- 解题思路:建立最小堆,维持堆内始终有K个元素,通过与堆顶元素比较,依次把符合条件的元素入堆,最后的堆顶元素为第k大的数。
- 代码实现:
#include<queue>
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
/*优先队列(小顶二叉堆)*/
priority_queue<int,vector<int>,greater<int>> Q;
for(int i = 0;i<nums.size();i++){
/*堆中元素小于k直接入堆*/
if(Q.size()<k){
Q.push(nums[i]);
/*堆顶比新元素小,弹出堆顶*/
}else if(Q.top()<nums[i]){
Q.pop();
Q.push(nums[i]);
}
}
return Q.top();
}
};
例6、寻找中位数(hard)(堆)
- 题目描述:
- 解题思路:动态维护一个最大堆和一个最小堆,最大堆保存前一半元素,最小堆保存后一半元素,始终保持最大堆的堆顶小于最小堆的堆顶,并保持最大堆与最小堆数量差的绝对值小于等于1,分三种情况进行讨论。
- 代码实现:
#include<queue>
class MedianFinder {
private:
//大顶堆
priority_queue<int,vector<int>>big_Q;
//小顶堆
priority_queue<int,vector<int>,greater<int>>small_Q;
public:
/** initialize your data structure here. */
MedianFinder() {
}
// 分四种情况进行讨论
void addNum(int num) {
// 如果都为空
if(big_Q.empty()&&small_Q.empty()){
big_Q.push(num);
}
//如果两个堆数量相等
else if(big_Q.size()==small_Q.size()){
if(num>big_Q.top()){
small_Q.push(num);
}else{
big_Q.push(num);
}
}
//如果大顶堆数量多一个
else if(big_Q.size()>small_Q.size()){
if(num>big_Q.top()){
small_Q.push(num);
}else{
int temp = big_Q.top();
big_Q.pop();
big_Q.push(num);
small_Q.push(temp);
}
}
//如果小顶堆数量多一个
else if(big_Q.size()<small_Q.size()){
if(num<small_Q.top()){
big_Q.push(num);
}else{
int temp = small_Q.top();
small_Q.pop();
small_Q.push(num);
big_Q.push(temp);
}
}
}
double findMedian() {
if(big_Q.size()==small_Q.size()){
return (big_Q.top()+small_Q.top())/2.0;
}
else if(big_Q.size()>small_Q.size()){
return big_Q.top();
}
else{
return small_Q.top();
}
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/