Stack Permutations (Check if a queue is stack permutation of other)
A stack permutation refers to the rearrangement of elements from an input queue to an output queue using a stack, where elements are transferred with the help of stack operations like push and pop. The rules are as follows:
- Dequeue elements only from the input queue.
- Utilize the stack’s built-in push and pop functions.
- Output Queue is initially empty and we need to fill the elements in desired order.
- Elements can only be dequeued from the input queue and enqueued into the output queue.
Since stack operations allow a variety of element sequences, a large number of permutations are possible for a single input queue.
Given two arrays, a[] and b[], where both arrays consist of unique elements:
a[]
represents the input queue.b[]
represents the desired output queue.
We need to check whether b[] can be obtained by performing stack permutation on a[]. This means that we can push and pop elements from the input queue (a[]) to an auxiliary stack, and then pop elements from the stack to form the output queue (b[]).
Examples:
Input: a[] = [ 1, 2, 3 ] , b[] = [ 2, 1, 3 ]
Output: True
Explanation:
1. push 1 from a to stack
2. push 2 from b to stack
3. pop 2 from stack to b
4. pop 1 from stack to b
5. push 3 from arr1 to stack
6. pop 3 from stack to bInput: a[] = [ 1, 2, 3 ] , b[] = [ 3, 1, 2 ]
Output: False
Explanation: Not Possible
[Naive Approach] – Creating an Actual Queue – O(n) time and O(n) space
We create both input and desired output queues using given arrays. We dequeue items one by one from input queue and it the dequeued item matches the front of output queue, then we remove from both queues. We also remove top of the stack and output queue if they match. Otherwise we push the dequeued item into the stack.
Please note that we only need to find out whether the input queue is permutable or 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, then dequeue from
// the output queue also
q2.pop();
// Now see if top of the stack
// also matches the front
while (!st.empty())
{
if (st.top() == q2.front())
{
st.pop();
q2.pop();
}
else
break;
}
}
else
st.push(ele);
}
bool res = (q1.empty() && st.empty());
cout << (res ? "True" : "False") << endl;
return res;
}
int main()
{
vector<int> a = {1, 2, 3};
vector<int> b = {2, 1, 3};
checkPerm(a, b);
return 0;
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class GfG {
public static boolean checkPerm(int[] a, int[] b) {
Queue<Integer> q1 = new LinkedList<>();
for (int i = 0; i < a.length; i++) q1.offer(a[i]);
Queue<Integer> q2 = new LinkedList<>();
for (int i = 0; i < b.length; i++) q2.offer(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, then dequeue from
// the output queue also
q2.poll();
// Now see if top of the stack
// also matches the front
while (!st.isEmpty()) {
if (st.peek() == q2.peek()) {
st.pop();
q2.poll();
} else
break;
}
} else
st.push(ele);
}
boolean res = (q1.isEmpty() && st.isEmpty());
System.out.println(res ? "True" : "False");
return res;
}
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = {2, 1, 3};
checkPerm(a, b);
}
}
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, then dequeue
# from the output queue also
q2.popleft()
# Now see if top of the stack
# also matches the front
while st and st[-1] == q2[0]:
st.pop()
q2.popleft()
else:
st.append(ele)
res = (not q1 and not st)
print("True" if res else "False")
return res
if __name__ == '__main__':
a = [1, 2, 3]
b = [2, 1, 3]
checkPerm(a, b)
using System;
using System.Collections.Generic;
class Program {
static bool CheckPerm(List<int> a, List<int> b) {
Queue<int> q1 = new Queue<int>();
foreach (var item in a) q1.Enqueue(item);
Queue<int> q2 = new Queue<int>();
foreach (var item in b) q2.Enqueue(item);
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, then dequeue from
// the output queue also
q2.Dequeue();
// Now see if top of the stack
// also matches the front
while (st.Count > 0) {
if (st.Peek() == q2.Peek()) {
st.Pop();
q2.Dequeue();
} else
break;
}
} else
st.Push(ele);
}
bool res = (q1.Count == 0 && st.Count == 0);
Console.WriteLine(res ? "True" : "False");
return res;
}
static void Main() {
List<int> a = new List<int> { 1, 2, 3 };
List<int> b = new List<int> { 2, 1, 3 };
CheckPerm(a, b);
}
}
function checkPerm(a, b) {
let q1 = [...a];
let q2 = [...b];
let st = [];
// Dequeue all items one by one
while (q1.length > 0) {
let ele = q1.shift();
if (ele === q2[0]) {
// If matches, then dequeue from the output queue also
q2.shift();
// Now see if top of the stack also matches the front
while (st.length > 0 && st[st.length - 1] === q2[0]) {
st.pop();
q2.shift();
}
} else {
st.push(ele);
}
}
let res = (q1.length === 0 && st.length === 0);
console.log(res ? "True" : "False");
return res;
}
let a = [1, 2, 3];
let b = [2, 1, 3];
checkPerm(a, b);
Output
True
[Expected Approach] Simulating Push and Pop – O(n) time and O(1) space
The idea is same as the above approach, but we not create queues here and do not change input arrays. It simulates the process of pushing elements from a[] onto a stack and popping them in the order required to match b[]. For each element in a[], it is pushed onto the stack, and then the top of the stack is compared to the current element of b[]. If they match, the element is popped from the stack and the next element in b[] is checked. The process continues until all elements of a[] are processed. If all elements in b[] can be matched and popped from the stack, it returns True (valid permutation), otherwise
False
(invalid permutation)
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
bool checkPerm(vector<int>& a, vector<int>& b) {
stack<int> st;
int j = 0;
// Traverse a[]
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 {
public static boolean checkPerm(int[] a, int[] b) {
Stack<Integer> st = new Stack<>();
int j = 0;
// Traverse a[]
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):
stack = []
j = 0
# Traverse a[]
for i in range(len(a)):
# Push top of a[] to stack
stack.append(a[i])
# Keep popping from stack while it
# matches front of the output queue
while stack and stack[-1] == b[j]:
stack.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 Program {
static bool CheckPerm(List<int> a, List<int> b) {
Stack<int> st = new Stack<int>();
int j = 0;
// Traverse a[]
for (int i = 0; i < a.Count; 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.Count > 0 && st.Peek() == b[j]) {
st.Pop();
j++;
}
}
return (j == b.Count);
}
static void Main() {
List<int> a = new List<int> { 1, 2, 3 };
List<int> b = new List<int> { 2, 1, 3 };
Console.WriteLine(CheckPerm(a, b) ? "True" : "False");
}
}
function checkPerm(a, b) {
const stack = [];
let j = 0;
// Traverse a[]
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;
}
const a = [1, 2, 3];
const b = [2, 1, 3];
console.log(checkPerm(a, b) ? 'True' : 'False');
Output
True