우리가 작업 할 스택이 다음과 같다고 가정 해 봅시다.
6 , minvalue=2
2 , minvalue=2
5 , minvalue=3
3 , minvalue=3
9 , minvalue=7
7 , minvalue=7
8 , minvalue=8
위의 표현에서 스택은 왼쪽 값으로 만 빌드되고 오른쪽 값의 [minvalue]는 하나의 변수에 저장되는 설명 목적으로 만 작성됩니다.
실제 문제는 최소값 인 값이 그 시점에서 제거 될 때 스택을 반복하지 않고 다음 최소 요소가 무엇인지 어떻게 알 수 있다는 것입니다.
예를 들어 6이 터졌을 때 스택에서와 같이 최소 요소가 2이기 때문에 최소 요소가 아니므로 최소 값을 업데이트하지 않고도 안전하게 제거 할 수 있습니다.
그러나 2를 뽑으면 최소값이 지금 2 인 것을 볼 수 있으며 이것이 튀어 나오면 최소값을 3으로 업데이트해야합니다.
Point1 :
이제주의 깊게 관찰하면이 특정 상태 [2, minvalue = 2]에서 minvalue = 3을 생성해야합니다. 또는 스택에서 depper로 이동하면이 특정 상태 [3, minvalue = 3]에서 minvalue = 7을 생성해야합니다. 또는 스택에서 더 depper로 이동하면이 특정 상태에서 minvalue = 8을 생성해야합니다 [7, minvalue = 7]
위의 3 가지 경우 모두에서 우리가 생성해야하는 값은 둘 다 동일한 두 변수에 따라 달라지는 공통점을 발견 했습니까? 옳은. 현재 최소값보다 작은 요소를 푸시 할 때 기본적으로 해당 요소를 스택에 푸시하고 최소값에서도 동일한 숫자를 업데이트하기 때문에 이런 일이 발생하는 이유입니다.
Point2 :
그래서 우리는 기본적으로 동일한 숫자의 중복을 스택에 한 번, minvalue 변수에 한 번 저장합니다. 위의 CASES에서 볼 수 있듯이이 중복을 피하고 유용한 데이터를 스택 또는 minvalue에 저장하여 이전 최소값을 생성하는 데 집중해야합니다.
push에 저장할 값이 minmumvalue보다 작을 때 스택에 무엇을 저장해야하는지 집중 해 보겠습니다. 이 변수의 이름을 y로 지정하겠습니다. 이제 스택은 다음과 같습니다.
6 , minvalue=2
y1 , minvalue=2
5 , minvalue=3
y2 , minvalue=3
9 , minvalue=7
y3 , minvalue=7
8 , minvalue=8
나는 그들 모두가 같은 가치를 가질 것이라는 혼동을 피하기 위해 그것들을 y1, y2, y3로 이름을 바꿨습니다.
Point3 :
이제 y1, y2 및 y3에 대한 제약 조건을 찾아 보겠습니다. minvalue와 동일한 요소를 팝했을 때만 pop ()을 수행하는 동안 minvalue를 정확히 업데이트해야 할 때를 기억하십니까? minvalue보다 큰 것을 팝하면 minvalue를 업데이트 할 필요가 없습니다. 따라서 minvalue의 업데이트를 트리거하려면 y1, y2 & y3이 해당하는 minvalue보다 작아야합니다. [우리는 중복을 피하기 위해 평등을 거부합니다 [Point2]] 그래서 제약은 [y <minValue]입니다.
이제 y를 채우기 위해 돌아와 보겠습니다. 값을 생성하고 푸시 할 때 y를 입력해야합니다. 기억하세요. push를 위해 오는 값을 prevMinvalue보다 작은 x로 취하고 실제로 스택에 푸시 할 값을 y로합시다. 따라서 한 가지는 newMinValue = x 및 y <newMinvalue라는 것이 분명합니다.
이제 우리는 prevMinvalue와 x (newMinvalue)의 도움으로 y를 계산해야합니다 (y는 newMinValue (x)보다 작은 숫자 일 수 있으므로 제약 조건을 충족 할 수있는 숫자를 찾아야합니다).
Let's do the math:
x < prevMinvalue [Given]
x - prevMinvalue < 0
x - prevMinValue + x < 0 + x [Add x on both side]
2*x - prevMinValue < x
this is the y which we were looking for less than x(newMinValue).
y = 2*x - prevMinValue. 'or' y = 2*newMinValue - prevMinValue 'or' y = 2*curMinValue - prevMinValue [taking curMinValue=newMinValue].
따라서 x를 푸시 할 때 prevMinvalue보다 작 으면 y [2 * x-prevMinValue]를 누르고 newMinValue = x를 업데이트합니다.
그리고 팝시 스택에 minValue보다 작은 것이 포함되어 있으면 minVAlue를 업데이트하는 트리거입니다. curMinValue와 y에서 prevMinValue를 계산해야합니다. y = 2 * curMinValue-prevMinValue [증명 됨] prevMinVAlue = 2 * curMinvalue-y.
2 * curMinValue-y는 지금 prevMinValue로 업데이트해야하는 숫자입니다.
동일한 논리에 대한 코드는 아래에서 O (1) 시간 및 O (1) 공간 복잡성으로 공유됩니다.
// C++ program to implement a stack that supports
// getMinimum() in O(1) time and O(1) extra space.
#include <bits/stdc++.h>
using namespace std;
// A user defined stack that supports getMin() in
// addition to push() and pop()
struct MyStack
{
stack<int> s;
int minEle;
// Prints minimum element of MyStack
void getMin()
{
if (s.empty())
cout << "Stack is empty\n";
// variable minEle stores the minimum element
// in the stack.
else
cout <<"Minimum Element in the stack is: "
<< minEle << "\n";
}
// Prints top element of MyStack
void peek()
{
if (s.empty())
{
cout << "Stack is empty ";
return;
}
int t = s.top(); // Top element.
cout << "Top Most Element is: ";
// If t < minEle means minEle stores
// value of t.
(t < minEle)? cout << minEle: cout << t;
}
// Remove the top element from MyStack
void pop()
{
if (s.empty())
{
cout << "Stack is empty\n";
return;
}
cout << "Top Most Element Removed: ";
int t = s.top();
s.pop();
// Minimum will change as the minimum element
// of the stack is being removed.
if (t < minEle)
{
cout << minEle << "\n";
minEle = 2*minEle - t;
}
else
cout << t << "\n";
}
// Removes top element from MyStack
void push(int x)
{
// Insert new number into the stack
if (s.empty())
{
minEle = x;
s.push(x);
cout << "Number Inserted: " << x << "\n";
return;
}
// If new number is less than minEle
if (x < minEle)
{
s.push(2*x - minEle);
minEle = x;
}
else
s.push(x);
cout << "Number Inserted: " << x << "\n";
}
};
// Driver Code
int main()
{
MyStack s;
s.push(3);
s.push(5);
s.getMin();
s.push(2);
s.push(1);
s.getMin();
s.pop();
s.getMin();
s.pop();
s.peek();
return 0;
}