สมมติว่าสแต็กที่เราจะดำเนินการคือ:
6 , minvalue=2
2 , minvalue=2
5 , minvalue=3
3 , minvalue=3
9 , minvalue=7
7 , minvalue=7
8 , minvalue=8
ในการแทนค่าด้านบนสแต็กถูกสร้างขึ้นโดยค่าทางซ้ายเท่านั้น [minvalue] ของค่าที่เหมาะสมจะถูกเขียนขึ้นเพื่อวัตถุประสงค์ในการอธิบายเท่านั้นซึ่งจะถูกเก็บไว้ในตัวแปรเดียว
ปัญหาที่แท้จริงคือเมื่อค่าซึ่งเป็นค่า minimun ถูกลบออก ณ จุดนั้นเราจะรู้ได้อย่างไรว่าอะไรคือองค์ประกอบขั้นต่ำถัดไปโดยไม่ต้องวนซ้ำบนสแตก
เช่นเดียวกับตัวอย่างในกองของเราเมื่อ 6 get โผล่ขึ้นมาเรารู้ว่านี่ไม่ใช่องค์ประกอบขั้นต่ำเนื่องจากองค์ประกอบขั้นต่ำคือ 2 ดังนั้นเราจึงสามารถลบสิ่งนี้ออกได้อย่างปลอดภัยโดยไม่ต้องอัปเดตค่าขั้นต่ำของเรา
แต่เมื่อเราปรากฏ 2 เราจะเห็นว่าค่าต่ำสุดคือ 2 ในขณะนี้และถ้าค่านี้โผล่ออกมาเราต้องอัปเดตค่าต่ำสุดเป็น 3
Point1:
ทีนี้ถ้าคุณสังเกตอย่างรอบคอบเราจำเป็นต้องสร้าง minvalue = 3 จากสถานะนี้ [2, minvalue = 2] หรือถ้าคุณไป depper ในสแต็กเราจำเป็นต้องสร้าง minvalue = 7 จากสถานะนี้ [3, minvalue = 3] หรือถ้าคุณเพิ่ม depper ในสแต็กมากขึ้นเราจำเป็นต้องสร้าง minvalue = 8 จากสถานะนี้ [7, minvalue = 7]
คุณสังเกตเห็นบางสิ่งที่เหมือนกันในทั้ง 3 กรณีข้างต้นค่าที่เราต้องสร้างขึ้นอยู่กับตัวแปรสองตัวซึ่งทั้งคู่เท่ากัน แก้ไข. เหตุใดสิ่งนี้จึงเกิดขึ้นเพราะเมื่อเราดันองค์ประกอบบางส่วนให้เล็กลงจากนั้นค่า minvalue ปัจจุบันโดยพื้นฐานแล้วเราจะดันองค์ประกอบนั้นในสแต็กและอัปเดตตัวเลขเดียวกันในค่าต่ำสุดด้วย
จุด 2:
ดังนั้นโดยทั่วไปเราจะจัดเก็บข้อมูลที่ซ้ำกันของหมายเลขเดียวกันหนึ่งครั้งในสแต็กและอีกครั้งในตัวแปร minvalue เราจำเป็นต้องให้ความสำคัญกับการหลีกเลี่ยงการทำซ้ำนี้และจัดเก็บข้อมูลที่เป็นประโยชน์ในสแต็กหรือค่าต่ำสุดเพื่อสร้างค่าต่ำสุดก่อนหน้าดังที่แสดงในกรณีด้านบน
มาเน้นที่สิ่งที่เราควรจัดเก็บใน stack เมื่อค่าที่จะจัดเก็บใน 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 ให้เป็น x ซึ่งน้อยกว่าค่า prevMinvalue และค่าที่เราจะดันใน stack ให้เป็น y ดังนั้นสิ่งหนึ่งที่ชัดเจนคือ newMinValue = x และ y <newMinvalue
ตอนนี้เราจำเป็นต้องคำนวณ y (จำ y สามารถเป็นตัวเลขใดก็ได้ที่น้อยกว่า newMinValue (x) ดังนั้นเราต้องหาจำนวนที่สามารถตอบสนองข้อ จำกัด ของเราได้) ด้วยความช่วยเหลือของ prevMinvalue และ x (newMinvalue)
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 เราต้องคำนวณ prevMinValue จาก curMinValue และ y y = 2 * curMinValue - prevMinValue [พิสูจน์แล้ว] prevMinVAlue = 2 * curMinvalue - y
2 * curMinValue - y คือตัวเลขที่เราต้องอัปเดตเป็น prevMinValue ทันที
โค้ดสำหรับตรรกะเดียวกันจะถูกแชร์ด้านล่างด้วย O (1) time และ O (1) space complexity
// 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;
}