Stack Permutations
We have an empty stack and can perform push and pop operations. We are given two arrays, a[] and b[], where a[] represents the order in which elements are pushed onto the stack, and b[] represents the order in which elements are popped from the stack. Find whether the given push and pop sequences are valid.
Examples:
Input: a[] = [1, 2, 3], b[] = [2, 1, 3]
Output: true
Explanation: Push 1 and 2. Since b[] requires 2 first, pop 2, then pop 1 next. Finally, push 3 and pop it. The push and pop sequence matches a[] and b[].Input: a[] = [1, 2, 3], b[] = [3, 1, 2]
Output: false
Explanation: After pushing 1, 2, and 3, we can pop 3 as required. But the next element in b[] is 1, while the stack top is 2. Since 1 is blocked under 2, this order cannot be achieved.
Table of Content
[Naive Approach] Using Queue - O(n) time and O(n) space
The idea is to simulate the stack operations while keeping track of the remaining elements to process using queues.
We push elements from a[] in order, and for each element, we check if it matches the front of b[] (the expected pop order). If it matches, we remove it from b[]; if not, we push it onto a stack. After each push, we also check the top of the stack if it matches the front of b[], we pop from the stack and remove it from b[]. By repeating this, we see if all elements in b[] can be matched. If yes, the pop sequence is valid; otherwise, it is not.
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
bool checkPerm(vector<int>& a, vector<int>& b) {
queue<int> q1;
for (int i = 0; i < a.size(); i++)
q1.push(a[i]);
queue<int> q2;
for (int i = 0; i < b.size(); i++)
q2.push(b[i]);
stack<int> st;
// Dequeue all items one by one
while (!q1.empty()) {
int ele = q1.front();
q1.pop();
if (ele == q2.front()) {
// If matches, dequeue from output queue
q2.pop();
// Pop from stack while top matches q2 front
while (!st.empty() && !q2.empty() && st.top() == q2.front()) {
st.pop();
q2.pop();
}
}
else {
st.push(ele);
}
}
return q2.empty();
}
int main() {
vector<int> a = {1, 2, 3};
vector<int> b = {3, 2, 1};
if (checkPerm(a, b))
cout << "true" << endl;
else
cout << "false" << endl;
return 0;
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class GfG {
static boolean checkPerm(int[] a, int[] b) {
Queue<Integer> q1 = new LinkedList<>();
for (int i = 0; i < a.length; i++)
q1.add(a[i]);
Queue<Integer> q2 = new LinkedList<>();
for (int i = 0; i < b.length; i++)
q2.add(b[i]);
Stack<Integer> st = new Stack<>();
// Dequeue all items one by one
while (!q1.isEmpty()) {
int ele = q1.poll();
if (ele == q2.peek()) {
// If matches, dequeue from output queue
q2.poll();
// Pop from stack while top matches q2 front
while (!st.isEmpty() && !q2.isEmpty() && st.peek() == q2.peek()) {
st.pop();
q2.poll();
}
}
else {
st.push(ele);
}
}
return q2.isEmpty();
}
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = {3, 2, 1};
if (checkPerm(a, b))
System.out.println("true");
else
System.out.println("false");
}
}
from collections import deque
def checkPerm(a, b):
q1 = deque(a)
q2 = deque(b)
st = []
# Dequeue all items one by one
while q1:
ele = q1.popleft()
if ele == q2[0]:
# If matches, dequeue from output queue
q2.popleft()
# Pop from stack while top matches q2 front
while st and q2 and st[-1] == q2[0]:
st.pop()
q2.popleft()
else:
st.append(ele)
return not q2
if __name__ == '__main__':
a = [1, 2, 3]
b = [3, 2, 1]
if checkPerm(a, b):
print('true')
else:
print('false')
using System;
using System.Collections.Generic;
public class GfG {
static bool checkPerm(int[] a, int[] b) {
Queue<int> q1 = new Queue<int>(a);
Queue<int> q2 = new Queue<int>(b);
Stack<int> st = new Stack<int>();
// Dequeue all items one by one
while (q1.Count > 0) {
int ele = q1.Dequeue();
if (ele == q2.Peek()) {
// If matches, dequeue from output queue
q2.Dequeue();
// Pop from stack while top matches q2 front
while (st.Count > 0 && q2.Count > 0 && st.Peek() == q2.Peek())
{
st.Pop();
q2.Dequeue();
}
}
else
{
st.Push(ele);
}
}
return q2.Count == 0;
}
public static void Main() {
int[] a = { 1, 2, 3 };
int[] b = { 3, 2, 1 };
if (checkPerm(a, b))
Console.WriteLine("true");
else
Console.WriteLine("false");
}
}
function checkPerm(a, b) {
// simulate queue with array
let q1 = a;
// simulate queue with array
let q2 = b;
let st = [];
// pointer for front of q1
let front1 = 0;
// pointer for front of q2
let front2 = 0;
while (front1 < q1.length) {
let ele = q1[front1];
front1++;
if (ele === q2[front2]) {
front2++;
// Pop from stack while top matches q2 front
while (st.length > 0 && st[st.length - 1] === q2[front2]) {
st.pop();
front2++;
}
} else {
st.push(ele);
}
}
return front2 === q2.length;
}
// Driver Code
let a = [1, 2, 3];
let b = [3, 2, 1];
console.log(checkPerm(a, b));
Output
true
[Expected Approach] Simulating Push and Pop - O(n) time and O(n) space
In this approach, we don’t actually build queues or modify the input arrays. Instead, we directly simulate the push and pop operations on a stack.
Each element from a[] is pushed onto the stack one by one. After every push, we check whether the top of the stack matches the current element of b[]. If it does, we pop it from the stack and move forward in b[]. This process repeats until all elements of a[] have been pushed and checked. If by the end all elements of b[] have been successfully matched and popped, the permutation is valid (returns true); otherwise, it is invalid (returns false).
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
bool checkPerm(vector<int>& a, vector<int>& b) {
stack<int> st;
int j = 0;
for (int i = 0; i < a.size(); i++) {
// Push top of a[] to stack
st.push(a[i]);
// Keep popping from stack while it
// matches front of the output queue
while (!st.empty() && st.top() == b[j]) {
st.pop();
j++;
}
}
return (j == b.size());
}
int main() {
vector<int> a = {1, 2, 3};
vector<int> b = {2, 1, 3};
cout << (checkPerm(a, b) ? "true" : "false") << endl;
return 0;
}
import java.util.Stack;
public class GfG {
static boolean checkPerm(int[] a, int[] b) {
Stack<Integer> st = new Stack<>();
int j = 0;
for (int i = 0; i < a.length; i++) {
// Push top of a[] to stack
st.push(a[i]);
// Keep popping from stack while it
// matches front of the output array
while (!st.isEmpty() && st.peek().equals(b[j])) {
st.pop();
j++;
}
}
return (j == b.length);
}
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = {2, 1, 3};
System.out.println(checkPerm(a, b) ? "true" : "false");
}
}
def checkPerm(a, b):
st = []
j = 0
for i in range(len(a)):
# Push top of a[] to stack
st.append(a[i])
# Keep popping from stack while it
# matches front of the output queue
while st and st[-1] == b[j]:
st.pop()
j += 1
return j == len(b)
if __name__ == '__main__':
a = [1, 2, 3]
b = [2, 1, 3]
print("true" if checkPerm(a, b) else "false")
using System;
using System.Collections.Generic;
class GfG {
static bool checkPerm(int[] a, int[] b) {
Stack<int> stack = new Stack<int>();
int j = 0;
for (int i = 0; i < a.Length; i++) {
// Push top of a[] to stack
stack.Push(a[i]);
// Keep popping from stack while it matches b[j]
while (stack.Count > 0 && stack.Peek() == b[j]) {
stack.Pop();
j++;
}
}
return j == b.Length;
}
static void Main() {
int[] a = { 1, 2, 3 };
int[] b = { 2, 1, 3 };
Console.WriteLine(checkPerm(a, b) ? "true" : "false");
}
}
function checkPerm(a, b) {
const stack = [];
let j = 0;
for (let i = 0; i < a.length; i++) {
// Push top of a[] to stack
stack.push(a[i]);
// Keep popping from stack while it
// matches front of the output queue
while (stack.length > 0 && stack[stack.length - 1] === b[j]) {
stack.pop();
j++;
}
}
return j === b.length;
}
//Driven Code
const a = [1, 2, 3];
const b = [2, 1, 3];
console.log(checkPerm(a, b) ? 'true' : 'false');
Output
true