thiết kế một ngăn xếp sao cho getMinimum () phải là O (1)


118

Đây là một trong những câu hỏi phỏng vấn. Bạn cần thiết kế một ngăn xếp chứa giá trị nguyên sao cho hàm getMinimum () sẽ trả về phần tử tối thiểu trong ngăn xếp.

Ví dụ: hãy xem xét ví dụ dưới đây

trường hợp 1

5 -> ĐẦU
1
4
6
2

Khi getMinimum () được gọi, nó sẽ trả về 1, là phần tử tối thiểu 
trong ngăn xếp. 

trường hợp số 2

stack.pop ()
stack.pop ()

Lưu ý: Cả 5 và 1 đều bật ra khỏi ngăn xếp. Vì vậy, sau này, ngăn xếp
giống như,

4 -> ĐẦU
6
2

Khi getMinimum () được gọi sẽ trả về 2, đây là giá trị tối thiểu trong 
cây rơm.

Hằng số:

  1. getMinimum sẽ trả về giá trị nhỏ nhất trong O (1)
  2. Hạn chế không gian cũng phải được xem xét khi thiết kế nó và nếu bạn sử dụng thêm không gian, nó phải là không gian cố định.

Câu trả lời:


180

CHỈNH SỬA: Điều này không thành công với ràng buộc "không gian không đổi" - về cơ bản nó tăng gấp đôi không gian cần thiết. Tôi rất nghi ngờ rằng có một giải pháp không làm được điều đó, mà không phá hủy độ phức tạp thời gian chạy ở đâu đó (ví dụ: tạo push / pop O (n)). Lưu ý rằng điều này không thay đổi độ phức tạp của không gian cần thiết, ví dụ: nếu bạn có một ngăn xếp với yêu cầu về không gian O (n), thì đây vẫn sẽ là O (n) chỉ với một hệ số không đổi khác.

Giải pháp không gian không đổi

Giữ một ngăn xếp "trùng lặp" gồm "tối thiểu của tất cả các giá trị thấp hơn trong ngăn xếp". Khi bạn bật ngăn xếp chính, cũng bật ngăn xếp tối thiểu. Khi bạn đẩy ngăn xếp chính, hãy đẩy phần tử mới hoặc phần tử tối thiểu hiện tại, tùy theo giá trị nào thấp hơn. getMinimum()sau đó được thực hiện như chỉ minStack.peek().

Vì vậy, sử dụng ví dụ của bạn, chúng tôi sẽ có:

Real stack        Min stack

5  --> TOP        1
1                 1
4                 2
6                 2
2                 2

Sau khi bật hai lần, bạn nhận được:

Real stack        Min stack

4                 2
6                 2
2                 2

Vui lòng cho tôi biết nếu điều này không đủ thông tin. Thật đơn giản khi bạn tìm hiểu nó, nhưng bạn có thể hơi khó chịu lúc đầu :)

(Tất nhiên, nhược điểm là nó tăng gấp đôi yêu cầu về không gian. Mặc dù vậy, thời gian thực thi không bị ảnh hưởng đáng kể - tức là nó vẫn có cùng độ phức tạp.)

CHỈNH SỬA: Có một biến thể hơi khó sử dụng hơn, nhưng nhìn chung có không gian tốt hơn. Chúng tôi vẫn có ngăn xếp tối thiểu, nhưng chúng tôi chỉ bật ra từ nó khi giá trị chúng tôi bật ra từ ngăn xếp chính bằng giá trị trên ngăn xếp tối thiểu. Chúng tôi chỉ đẩy lên ngăn xếp min khi giá trị được đẩy lên ngăn xếp chính nhỏ hơn hoặc bằng giá trị min hiện tại. Điều này cho phép các giá trị tối thiểu trùng lặp. getMinimum()vẫn chỉ là một hoạt động xem trước. Ví dụ: lấy phiên bản gốc và đẩy lại 1 lần nữa, chúng tôi sẽ nhận được:

Real stack        Min stack

1  --> TOP        1
5                 1
1                 2
4                 
6                 
2                 

Popping từ trên bật ra từ cả hai ngăn xếp vì 1 == 1, để lại:

Real stack        Min stack

5  --> TOP        1
1                 2
4                 
6                 
2                 

Popping lại chỉ xuất hiện từ ngăn xếp chính, vì 5> 1:

Real stack        Min stack

1                 1
4                 2
6                 
2                 

Popping lại bật ra cả hai ngăn xếp vì 1 == 1:

Real stack        Min stack

4                 2
6                 
2                 

Điều này kết thúc với cùng một độ phức tạp không gian trong trường hợp xấu nhất (gấp đôi ngăn xếp ban đầu) nhưng sử dụng không gian tốt hơn nhiều nếu chúng ta hiếm khi nhận được "mức tối thiểu hoặc bằng mới".

CHỈNH SỬA: Đây là một triển khai kế hoạch xấu xa của Pete. Mình chưa test kỹ nhưng thấy ổn :)

using System.Collections.Generic;

public class FastMinStack<T>
{
    private readonly Stack<T> stack = new Stack<T>();
    // Could pass this in to the constructor
    private readonly IComparer<T> comparer = Comparer<T>.Default;

    private T currentMin;

    public T Minimum
    {
        get { return currentMin; }
    }

    public void Push(T element)
    {
        if (stack.Count == 0 ||
            comparer.Compare(element, currentMin) <= 0)
        {
            stack.Push(currentMin);
            stack.Push(element);
            currentMin = element;
        }
        else
        {
            stack.Push(element);
        }
    }

    public T Pop()
    {
        T ret = stack.Pop();
        if (comparer.Compare(ret, currentMin) == 0)
        {
            currentMin = stack.Pop();
        }
        return ret;
    }
}

3
Tài giỏi! @Ganesh: Tại sao thời gian chạy lại là một vấn đề? Nó sẽ chỉ mất gấp đôi thời gian so với một ngăn xếp đơn lẻ, tức là vẫn còn O (1) thời gian cho push () và pop () cũng như getMinimum () - đó là hiệu suất tuyệt vời !
j_random_hacker

4
Nếu bạn có một biến duy nhất, điều gì sẽ xảy ra khi bạn chọn "1" trong ví dụ của mình? Nó phải tìm ra rằng mức tối thiểu trước đó là "2" - mà nó không thể không quét qua mọi thứ.
Jon Skeet

1
@Ganesh: Sau đó, bạn sẽ không cần tìm mức tối thiểu mới bằng cách sử dụng tìm kiếm O (n) bất cứ khi nào bạn bật ()?
j_random_hacker

2
Chỉ cần đọc các bình luận khác của bạn, khi bạn nói "trong bản thân thiết kế ngăn xếp", bạn có nghĩa là "trong mỗi phần tử"? Nếu vậy, bạn vẫn có khả năng tăng gần gấp đôi yêu cầu bộ nhớ, tùy thuộc vào kích thước của loại phần tử. Về mặt khái niệm, nó giống như hai ngăn xếp.
Jon Skeet

1
@Ganesh: Rất tiếc, không có ngăn xếp bổ sung có nghĩa là chúng tôi không thể thực hiện tối ưu hóa tiết kiệm không gian mà tôi đã bao gồm ở trên. Giữ "tối thiểu và phần tử" cùng nhau có lẽ hiệu quả hơn hai ngăn xếp có cùng kích thước (ít chi phí hơn - mảng, nút danh sách, v.v.) mặc dù nó sẽ phụ thuộc vào ngôn ngữ.
Jon Skeet

41

Thêm trường để giữ giá trị nhỏ nhất và cập nhật nó trong Pop () và Push (). Theo cách đó getMinimum () sẽ là O (1), nhưng Pop () và Push () sẽ phải làm nhiều việc hơn một chút.

Nếu giá trị nhỏ nhất được bật lên, Pop () sẽ là O (n), nếu không chúng vẫn là O (1). Khi thay đổi kích thước Push () trở thành O (n) theo việc triển khai Ngăn xếp.

Đây là cách triển khai nhanh chóng

public sealed class MinStack {
    private int MinimumValue;
    private readonly Stack<int> Stack = new Stack<int>();

    public int GetMinimum() {
        if (IsEmpty) {
            throw new InvalidOperationException("Stack is empty");
        }
        return MinimumValue;
    }

    public int Pop() {
        var value = Stack.Pop();
        if (value == MinimumValue) {
            MinimumValue = Stack.Min();
        }
        return value;
    }

    public void Push(int value) {
        if (IsEmpty || value < MinimumValue) {
            MinimumValue = value;
        }
        Stack.Push(value);
    }

    private bool IsEmpty { get { return Stack.Count() == 0; } }
}

xin lỗi tôi không hiểu tại sao pop () và push () sẽ bị ảnh hưởng?
Ganesh M

11
Trong pop () phần tử tối thiểu "mới" phải được tìm thấy, lấy O (n). Push () sẽ không bị ảnh hưởng, vì thao tác này vẫn là O (1).
Georg Schölly

4
@sigjuice: đúng. Tôi nghĩ mình sẽ thay đổi từ "đau khổ" một cái gì đó ít kịch tính :)
Brian Rasmussen

2
@Ganesh M "trường bổ sung các phần tử" nếu bạn có một trường bổ sung trong N phần tử của mình, đó không phải là không gian hằng số, mà là thêm O (N).
Pete Kirkham

1
Nếu giá trị nhỏ nhất được bật ra khỏi ngăn xếp trong một hoạt động, thì giá trị nhỏ nhất tiếp theo được tìm thấy như thế nào? Phương pháp này không hỗ trợ mà kịch bản ...
Sharat Chandra

16
public class StackWithMin {
    int min;
    int size;
    int[] data = new int[1024];

    public void push ( int val ) {
        if ( size == 0 ) {
            data[size] = val;
            min = val;
        } else if ( val < min) {
            data[size] = 2 * val - min;
            min = val;

            assert (data[size] < min); 
        } else {
            data[size] = val;
        }

        ++size;

        // check size and grow array
    }

    public int getMin () {
        return min;
    }

    public int pop () {
        --size;

        int val = data[size];

        if ( ( size > 0 ) && ( val < min ) ) {
            int prevMin = min;
            min += min - val;
            return prevMin;
        } else {
            return val;
        }
    }

    public boolean isEmpty () {
        return size == 0;
    }

    public static void main (String...args) {
        StackWithMin stack = new StackWithMin();

        for ( String arg: args ) 
            stack.push( Integer.parseInt( arg ) );

        while ( ! stack.isEmpty() ) {
            int min = stack.getMin();
            int val = stack.pop();

            System.out.println( val + " " + min );
        }

        System.out.println();
    }

}

Nó lưu trữ mức tối thiểu hiện tại một cách rõ ràng và nếu mức tối thiểu thay đổi, thay vì đẩy giá trị, nó sẽ đẩy một giá trị có cùng mức chênh lệch sang phía bên kia của mức tối thiểu mới (nếu min = 7 và bạn đẩy 5, nó sẽ đẩy 3 thay vào đó (5 | 7-5 | = 3) và đặt min thành 5; nếu sau đó bạn bật 3 khi min là 5, nó sẽ thấy rằng giá trị xuất hiện nhỏ hơn min, vì vậy hãy đảo ngược quy trình để lấy 7 cho min mới, sau đó trả về giá trị trước đó tối thiểu). Vì bất kỳ giá trị nào không gây ra thay đổi, giá trị tối thiểu hiện tại lớn hơn giá trị tối thiểu hiện tại, bạn có một cái gì đó có thể được sử dụng để phân biệt giữa giá trị thay đổi giá trị tối thiểu và giá trị nào không.

Trong các ngôn ngữ sử dụng số nguyên có kích thước cố định, bạn đang mượn một chút không gian từ việc biểu diễn các giá trị, vì vậy nó có thể bị tràn và xác nhận sẽ không thành công. Nhưng nếu không, đó là không gian thừa không đổi và tất cả các phép toán vẫn là O (1).

Các ngăn xếp thay vì dựa trên danh sách được liên kết có những nơi khác mà bạn có thể mượn một chút, ví dụ trong C là bit quan trọng nhất của con trỏ tiếp theo hoặc trong Java loại đối tượng trong danh sách được liên kết. Đối với Java, điều này có nghĩa là có nhiều không gian hơn được sử dụng so với một ngăn xếp liền kề, vì bạn có chi phí đối tượng cho mỗi liên kết:

public class LinkedStackWithMin {
    private static class Link {
        final int value;
        final Link next;

        Link ( int value, Link next ) {
            this.value = value;
            this.next = next;
        }

        int pop ( LinkedStackWithMin stack ) {
            stack.top = next;
            return value;
        }
    }

    private static class MinLink extends Link {
        MinLink ( int value, Link next ) {
            super( value, next );
        }

        int pop ( LinkedStackWithMin stack ) {
            stack.top = next;
            int prevMin = stack.min;
            stack.min = value;
            return prevMin;
        }
    }

    Link top;
    int min;

    public LinkedStackWithMin () {
    }

    public void push ( int val ) {
        if ( ( top == null ) || ( val < min ) ) {
            top = new MinLink(min, top);
            min = val;
        } else {
            top = new Link(val, top);
        }
    }

    public int pop () {
        return top.pop(this);
    }

    public int getMin () {
        return min;
    }

    public boolean isEmpty () {
        return top == null;
    }

Trong C, chi phí không có ở đó, và bạn có thể mượn lsb của con trỏ tiếp theo:

typedef struct _stack_link stack_with_min;

typedef struct _stack_link stack_link;

struct _stack_link {
    size_t  next;
    int     value;
};

stack_link* get_next ( stack_link* link ) 
{
    return ( stack_link * )( link -> next & ~ ( size_t ) 1 );
}

bool is_min ( stack_link* link )
{
    return ( link -> next & 1 ) ! = 0;
}

void push ( stack_with_min* stack, int value )
{
    stack_link *link = malloc ( sizeof( stack_link ) );

    link -> next = ( size_t ) stack -> next;

    if ( (stack -> next == 0) || ( value == stack -> value ) ) {
        link -> value = stack -> value;
        link -> next |= 1; // mark as min
    } else {
        link -> value = value;
    }

    stack -> next = link;
}

etc.;

Tuy nhiên, không ai trong số này thực sự là O (1). Chúng không yêu cầu thêm không gian trong thực tế, bởi vì chúng khai thác các lỗ hổng trong biểu diễn số, đối tượng hoặc con trỏ trong các ngôn ngữ này. Nhưng một máy lý thuyết sử dụng một biểu diễn nhỏ gọn hơn sẽ yêu cầu thêm một bit vào biểu diễn đó trong mỗi trường hợp.


+1 thực sự rất thanh lịch ... phiên bản C ++ đã được chuyển một cách nhẹ nhàng chạy tại Ideone đây . Chúc mừng.
Tony Delroy,

Trong Java, điều này sẽ tạo ra kết quả sai pop()nếu giá trị được đẩy cuối cùng là Integer.MIN_VALUE(ví dụ: push 1, push Integer.MIN_VALUE, pop). Điều này là do dòng chảy như đã đề cập ở trên. Nếu không thì hoạt động cho tất cả các giá trị nguyên.
Theo

13

Tôi đã tìm thấy một giải pháp thỏa mãn tất cả các ràng buộc đã đề cập (các hoạt động thời gian không đổi) và không gian thừa không đổi .

Ý tưởng là lưu trữ sự khác biệt giữa giá trị nhỏ nhất và số đầu vào, và cập nhật giá trị nhỏ nhất nếu nó không còn là giá trị nhỏ nhất.

Mã như sau:

public class MinStack {
    long min;
    Stack<Long> stack;

    public MinStack(){
        stack = new Stack<>();
    }

    public void push(int x) {
        if (stack.isEmpty()) {
            stack.push(0L);
            min = x;
        } else {
            stack.push(x - min); //Could be negative if min value needs to change
            if (x < min) min = x;
        }
    }

    public int pop() {
        if (stack.isEmpty()) return;

        long pop = stack.pop();

        if (pop < 0) {
            long ret = min
            min = min - pop; //If negative, increase the min value
            return (int)ret;
        }
        return (int)(pop + min);

    }

    public int top() {
        long top = stack.peek();
        if (top < 0) {
            return (int)min;
        } else {
           return (int)(top + min);
        }
    }

    public int getMin() {
        return (int)min;
    }
}

Tín dụng được chuyển đến: https://leetcode.com/discuss/15679/share-my-java-solution-with-only-one-stack


Cái này hoạt động. Tôi cũng đã thử với các số âm trong ngăn xếp. Và cũng đủ đơn giản để nhớ. Cảm ơn.
r9891

7

Chà, các ràng buộc về thời gian chạy là gì pushpop? Nếu chúng không bắt buộc phải là hằng số, thì chỉ cần tính giá trị nhỏ nhất trong hai phép toán đó (biến chúng thành O ( n )). Nếu không, tôi không biết làm thế nào điều này có thể được thực hiện với không gian bổ sung liên tục.


4
+1, hehe ... Thủ thuật "bẻ cong quy tắc" cũ ... Theo cách tương tự, tôi biết về một thuật toán sắp xếp sắp xếp bất kỳ mảng kích thước nào trong thời gian O (1), nhưng quyền truy cập đầu tiên vào bất kỳ phần tử nào của kết quả phát sinh chi phí O (nlog n) ... :)
j_random_hacker

3
Trong Haskell, mọi thứ đều là thời gian không đổi! (trừ khi bạn muốn in kết quả)
Henk

1
+1 để ghi nhận đặc tả vấn đề kém. "Tôi không thấy thế nào điều này có thể được thực hiện" - không phải đã làm tôi, nhưng giải pháp Pete Kirkham của làm nó rất thanh lịch ....
Tony Delroy

1

Đây là Mã của tôi chạy với O (1). Mã trước đó mà tôi đã đăng đã gặp sự cố khi phần tử tối thiểu được xuất hiện. Tôi đã sửa đổi mã của mình. Cái này sử dụng một Ngăn xếp khác duy trì phần tử tối thiểu hiện diện trong ngăn xếp phía trên phần tử được đẩy hiện tại.

 class StackDemo
{
    int[] stk = new int[100];
    int top;
    public StackDemo()
    {
        top = -1;
    }
    public void Push(int value)
    {
        if (top == 100)
            Console.WriteLine("Stack Overflow");
        else
            stk[++top] = value;
    }
    public bool IsEmpty()
    {
        if (top == -1)
            return true;
        else
            return false;
    }
    public int Pop()
    {
        if (IsEmpty())
        {
            Console.WriteLine("Stack Underflow");
            return 0;
        }
        else
            return stk[top--];
    }
    public void Display()
    {
        for (int i = top; i >= 0; i--)
            Console.WriteLine(stk[i]);
    }
}
class MinStack : StackDemo
{
    int top;
    int[] stack = new int[100];
    StackDemo s1; int min;
    public MinStack()
    {
        top = -1;
        s1 = new StackDemo();
    }
    public void PushElement(int value)
    {
        s1.Push(value);
        if (top == 100)
            Console.WriteLine("Stack Overflow");
        if (top == -1)
        {
            stack[++top] = value;
            stack[++top] = value;   
        }
        else
        {
            //  stack[++top]=value;
            int ele = PopElement();
            stack[++top] = ele;
            int a = MininmumElement(min, value);
              stack[++top] = min;

                stack[++top] = value;
                stack[++top] = a;


        }
    }
    public int PopElement()
    {

        if (top == -1)
            return 1000;
        else
        {
            min = stack[top--];
            return stack[top--];
        }

    }
    public int PopfromStack()
    {
        if (top == -1)
            return 1000;
        else
        {
            s1.Pop();
            return PopElement();
        }
    }
    public int MininmumElement(int a,int b)
    {
        if (a > b)
            return b;
        else
            return a;
    }
    public int StackTop()
    {
        return stack[top];
    }
    public void DisplayMinStack()
    {
        for (int i = top; i >= 0; i--)
            Console.WriteLine(stack[i]);
    }
}
class Program
{
    static void Main(string[] args)
    {
        MinStack ms = new MinStack();
        ms.PushElement(15);
        ms.PushElement(2);
        ms.PushElement(1);
        ms.PushElement(13);
        ms.PushElement(5);
        ms.PushElement(21);
        Console.WriteLine("Min Stack");
        ms.DisplayMinStack();
        Console.WriteLine("Minimum Element:"+ms.StackTop());
        ms.PopfromStack();
        ms.PopfromStack();
        ms.PopfromStack();
        ms.PopfromStack();

        Console.WriteLine("Min Stack");
        ms.DisplayMinStack();
        Console.WriteLine("Minimum Element:" + ms.StackTop());
        Thread.Sleep(1000000);
    }
}

3
Vui lòng đề cập đến ngôn ngữ lập trình được sử dụng ở đây để viết mã. Nó giúp khách truy cập tiềm năng biết được điều gì đang xảy ra dựa trên cú pháp. Tôi giả sử đó là C # nhưng nếu ai đó không làm như vậy thì sao?
realPK

1

Tôi đã sử dụng một loại ngăn xếp khác. Đây là cách thực hiện.

//
//  main.cpp
//  Eighth
//
//  Created by chaitanya on 4/11/13.
//  Copyright (c) 2013 cbilgika. All rights reserved.
//

#include <iostream>
#include <limits>
using namespace std;
struct stack
{
    int num;
    int minnum;
}a[100];

void push(int n,int m,int &top)
{

    top++;
    if (top>=100) {
        cout<<"Stack Full";
        cout<<endl;
    }
    else{
        a[top].num = n;
        a[top].minnum = m;
    }


}

void pop(int &top)
{
    if (top<0) {
        cout<<"Stack Empty";
        cout<<endl;
    }
    else{
       top--; 
    }


}
void print(int &top)
{
    cout<<"Stack: "<<endl;
    for (int j = 0; j<=top ; j++) {
        cout<<"("<<a[j].num<<","<<a[j].minnum<<")"<<endl;
    }
}


void get_min(int &top)
{
    if (top < 0)
    {
        cout<<"Empty Stack";
    }
    else{
        cout<<"Minimum element is: "<<a[top].minnum;
    }
    cout<<endl;
}

int main()
{

    int top = -1,min = numeric_limits<int>::min(),num;
    cout<<"Enter the list to push (-1 to stop): ";
    cin>>num;
    while (num!=-1) {
        if (top == -1) {
            min = num;
            push(num, min, top);
        }
        else{
            if (num < min) {
                min = num;
            }
            push(num, min, top);
        }
        cin>>num;
    }
    print(top);
    get_min(top);
    return 0;
}

Đầu ra:

Enter the list to push (-1 to stop): 5
1
4
6
2
-1
Stack: 
(5,5)
(1,1)
(4,1)
(6,1)
(2,1)
Minimum element is: 1

Thử nó. Tôi nghĩ nó trả lời câu hỏi. Phần tử thứ hai của mọi cặp cho giá trị nhỏ nhất được nhìn thấy khi phần tử đó được chèn vào.


1

Tôi đang đăng mã hoàn chỉnh ở đây để tìm tối thiểu và tối đa trong một ngăn xếp nhất định.

Độ phức tạp về thời gian sẽ là O (1) ..

package com.java.util.collection.advance.datastructure;

/**
 * 
 * @author vsinha
 *
 */
public abstract interface Stack<E> {

    /**
     * Placing a data item on the top of the stack is called pushing it
     * @param element
     * 
     */
    public abstract void push(E element);


    /**
     * Removing it from the top of the stack is called popping it
     * @return the top element
     */
    public abstract E pop();

    /**
     * Get it top element from the stack and it 
     * but the item is not removed from the stack, which remains unchanged
     * @return the top element
     */
    public abstract E peek();

    /**
     * Get the current size of the stack.
     * @return
     */
    public abstract int size();


    /**
     * Check whether stack is empty of not.
     * @return true if stack is empty, false if stack is not empty
     */
    public abstract boolean empty();



}



package com.java.util.collection.advance.datastructure;

@SuppressWarnings("hiding")
public abstract interface MinMaxStack<Integer> extends Stack<Integer> {

    public abstract int min();

    public abstract int max();

}


package com.java.util.collection.advance.datastructure;

import java.util.Arrays;

/**
 * 
 * @author vsinha
 *
 * @param <E>
 */
public class MyStack<E> implements Stack<E> {

    private E[] elements =null;
    private int size = 0;
    private int top = -1;
    private final static int DEFAULT_INTIAL_CAPACITY = 10;


    public MyStack(){
        // If you don't specify the size of stack. By default, Stack size will be 10
        this(DEFAULT_INTIAL_CAPACITY);
    }

    @SuppressWarnings("unchecked")
    public MyStack(int intialCapacity){
        if(intialCapacity <=0){
            throw new IllegalArgumentException("initial capacity can't be negative or zero");
        }
        // Can't create generic type array
        elements =(E[]) new Object[intialCapacity];
    }

    @Override
    public void push(E element) {
        ensureCapacity();
        elements[++top] = element;
        ++size;
    }

    @Override
    public E pop() {
        E element = null;
        if(!empty()) {
            element=elements[top];
            // Nullify the reference
            elements[top] =null;
            --top;
            --size;
        }
        return element;
    }

    @Override
    public E peek() {
        E element = null;
        if(!empty()) {
            element=elements[top];
        }
        return element;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean empty() {
        return size == 0;
    }

    /**
     * Increases the capacity of this <tt>Stack by double of its current length</tt> instance, 
     * if stack is full 
     */
    private void ensureCapacity() {
        if(size != elements.length) {
            // Don't do anything. Stack has space.
        } else{
            elements = Arrays.copyOf(elements, size *2);
        }
    }

    @Override
    public String toString() {
        return "MyStack [elements=" + Arrays.toString(elements) + ", size="
                + size + ", top=" + top + "]";
    }


}


package com.java.util.collection.advance.datastructure;

/**
 * Time complexity will be O(1) to find min and max in a given stack.
 * @author vsinha
 *
 */
public class MinMaxStackFinder extends MyStack<Integer> implements MinMaxStack<Integer> {

    private MyStack<Integer> minStack;

    private MyStack<Integer> maxStack;

    public MinMaxStackFinder (int intialCapacity){
        super(intialCapacity);
        minStack =new MyStack<Integer>();
        maxStack =new MyStack<Integer>();

    }
    public void push(Integer element) {
        // Current element is lesser or equal than min() value, Push the current element in min stack also.
        if(!minStack.empty()) {
            if(min() >= element) {
                minStack.push(element);
            }
        } else{
            minStack.push(element);
        }
        // Current element is greater or equal than max() value, Push the current element in max stack also.
        if(!maxStack.empty()) {
            if(max() <= element) {
                maxStack.push(element);
            }
        } else{
            maxStack.push(element);
        }
        super.push(element);
    }


    public Integer pop(){
        Integer curr = super.pop();
        if(curr !=null) {
            if(min() == curr) {
                minStack.pop();
            } 

            if(max() == curr){
                maxStack.pop();
            }
        }
        return curr;
    }


    @Override
    public int min() {
        return minStack.peek();
    }

    @Override
    public int max() {
        return maxStack.peek();
    }


    @Override
    public String toString() {
        return super.toString()+"\nMinMaxStackFinder [minStack=" + minStack + "\n maxStack="
                + maxStack + "]" ;
    }




}

// You can use the below program to execute it.

package com.java.util.collection.advance.datastructure;

import java.util.Random;

public class MinMaxStackFinderApp {

    public static void main(String[] args) {
        MinMaxStack<Integer> stack =new MinMaxStackFinder(10);
        Random random =new Random();
        for(int i =0; i< 10; i++){
            stack.push(random.nextInt(100));
        }
        System.out.println(stack);
        System.out.println("MAX :"+stack.max());
        System.out.println("MIN :"+stack.min());

        stack.pop();
        stack.pop();
        stack.pop();
        stack.pop();
        stack.pop();

        System.out.println(stack);
        System.out.println("MAX :"+stack.max());
        System.out.println("MIN :"+stack.min());
    }
}

Hãy cho tôi biết nếu bạn đang gặp phải bất kỳ vấn đề nào

Cảm ơn, Vikash


1

Bạn có thể mở rộng lớp ngăn xếp ban đầu của mình và chỉ cần thêm theo dõi tối thiểu vào nó. Hãy để lớp cha ban đầu xử lý mọi thứ khác như bình thường.

public class StackWithMin extends Stack<Integer> {  

    private Stack<Integer> min;

    public StackWithMin() {
        min = new Stack<>();
    }

    public void push(int num) {
        if (super.isEmpty()) {
            min.push(num);
        } else if (num <= min.peek()) {
            min.push(num);
        }
        super.push(num);
    }

    public int min() {
        return min.peek();
    }

    public Integer pop() {
        if (super.peek() == min.peek()) {
            min.pop();
        }
        return super.pop();
    }   
}

Giải pháp này cũng đang sử dụng thêm không gian về Stack <Integer> min.
Arpit

1

Đây là giải pháp của tôi trong java bằng cách sử dụng danh sách thích.

class Stack{
    int min;
    Node top;
    static class Node{
        private int data;
        private Node next;
        private int min;

        Node(int data, int min){
           this.data = data;
           this.min = min;
           this.next = null; 
    }
}

  void push(int data){
        Node temp;
        if(top == null){
            temp = new Node(data,data);
            top = temp;
            top.min = data;
        }
        if(top.min > data){
            temp = new Node(data,data);
            temp.next = top;
            top = temp;
        } else {
            temp = new Node(data, top.min);
            temp.next = top;
            top = temp;
        }
  }

  void pop(){
    if(top != null){
        top = top.next;
    }
  }

  int min(){
    return top.min;
  }

}


1

Hãy giả sử ngăn xếp mà chúng ta sẽ làm việc là:

6 , minvalue=2
2 , minvalue=2
5 , minvalue=3
3 , minvalue=3
9 , minvalue=7
7 , minvalue=7
8 , minvalue=8

Trong biểu diễn trên, ngăn xếp chỉ được xây dựng bởi giá trị bên trái, [giá trị tối thiểu] của giá trị bên phải chỉ được viết cho mục đích minh họa sẽ được lưu trữ trong một biến.

Vấn đề thực tế là khi giá trị là giá trị minimun nhận được bị loại bỏ tại thời điểm đó làm thế nào chúng ta có thể biết đâu là phần tử tối thiểu tiếp theo mà không cần lặp qua ngăn xếp.

Ví dụ như trong ngăn xếp của chúng tôi khi 6 get xuất hiện, chúng tôi biết rằng, đây không phải là phần tử tối thiểu vì phần tử tối thiểu là 2, vì vậy chúng tôi có thể loại bỏ điều này một cách an toàn mà không cần cập nhật giá trị tối thiểu của chúng tôi.

Nhưng khi bật 2, chúng ta có thể thấy rằng giá trị nhỏ nhất hiện tại là 2 và nếu giá trị này xuất hiện thì chúng ta cần cập nhật giá trị tối thiểu thành 3.

Điểm 1:

Bây giờ nếu bạn quan sát kỹ, chúng ta cần tạo minvalue = 3 từ trạng thái cụ thể này [2, minvalue = 2]. hoặc nếu bạn đi depperin ngăn xếp, chúng tôi cần tạo minvalue = 7 từ trạng thái cụ thể này [3, minvalue = 3] hoặc nếu bạn đi nhiều depper hơn trong ngăn xếp thì chúng tôi cần tạo minvalue = 8 từ trạng thái cụ thể này [7, minvalue = 7]

Bạn có nhận thấy điểm chung trong cả 3 trường hợp trên là giá trị mà chúng ta cần tạo ra phụ thuộc vào hai biến cả hai đều bằng nhau. Chính xác. Tại sao điều này lại xảy ra bởi vì khi chúng tôi đẩy một số phần tử nhỏ hơn giá trị tối thiểu hiện tại, thì về cơ bản chúng tôi đẩy phần tử đó vào ngăn xếp và cập nhật cùng một số trong giá trị tối thiểu cũng vậy.

Điểm 2:

Vì vậy, về cơ bản chúng ta đang lưu trữ bản sao của cùng một số một lần trong ngăn xếp và một lần trong biến giá trị tối thiểu. Chúng ta cần tập trung vào việc tránh trùng lặp này và lưu trữ dữ liệu hữu ích nào đó trong ngăn xếp hoặc giá trị tối thiểu để tạo ra mức tối thiểu trước đó như được hiển thị trong các TRƯỜNG HỢP ở trên.

Hãy tập trung vào những gì chúng ta nên lưu trữ trong ngăn xếp khi giá trị cần lưu trữ trong lần đẩy nhỏ hơn giá trị minmumvalue. Hãy đặt tên cho biến này là y, vì vậy bây giờ ngăn xếp của chúng ta sẽ trông giống như sau:

6 , minvalue=2
y1 , minvalue=2
5 , minvalue=3
y2 , minvalue=3
9 , minvalue=7
y3 , minvalue=7
8 , minvalue=8

Tôi đã đổi tên chúng thành y1, y2, y3 để tránh nhầm lẫn rằng tất cả chúng sẽ có cùng giá trị.

Điểm 3:

Bây giờ, hãy thử tìm một số ràng buộc trên y1, y2 và y3. Bạn có nhớ chính xác khi nào chúng ta cần cập nhật giá trị tối thiểu trong khi thực hiện pop (), chỉ khi chúng ta đã bật phần tử bằng giá trị tối thiểu. Nếu chúng tôi bật thứ gì đó lớn hơn giá trị tối thiểu thì chúng tôi không phải cập nhật giá trị tối thiểu. Vì vậy, để kích hoạt cập nhật giá trị tối thiểu, y1, y2 & y3 phải nhỏ hơn giá trị tối thiểu tương ứng. [Chúng tôi sử dụng bình đẳng để tránh trùng lặp [Point2]] vì vậy ràng buộc là [y <minValue].

Bây giờ chúng ta hãy quay lại điền y, chúng ta cần tạo ra một số giá trị và đặt y tại thời điểm đẩy, hãy nhớ. Hãy lấy giá trị sắp đẩy là x nhỏ hơn Giá trị hiện tại và giá trị mà chúng ta thực sự sẽ đẩy trong ngăn xếp là y. Vì vậy, một điều hiển nhiên là newMinValue = x và y <newMinvalue.

Bây giờ chúng ta cần tính toán y (hãy nhớ y có thể là một số bất kỳ nhỏ hơn newMinValue (x), vì vậy chúng ta cần tìm một số có thể đáp ứng ràng buộc của chúng ta) với sự trợ giúp của giá trị trước và x (giá trị mới).

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].

Vì vậy, tại thời điểm đẩy x nếu nó nhỏ hơn giá trị trước thì chúng ta đẩy y [2 * x-prevMinValue] và cập nhật newMinValue = x.

Và tại thời điểm bật lên nếu ngăn xếp chứa thứ gì đó nhỏ hơn minValue thì đó là trình kích hoạt của chúng tôi để cập nhật minVAlue. Chúng ta phải tính toán giá trị trước khi thu được từ curMinValue và y. y = 2 * curMinValue - prevMinValue [Đã chứng minh] prevMinVAlue = 2 * curMinvalue - y.

2 * curMinValue - y là số mà chúng ta cần cập nhật ngay bây giờ lên giá trị trước.

Mã cho cùng một logic được chia sẻ dưới đây với độ phức tạp O (1) thời gian và O (1) không gian.

// 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; 
} 

0

Đây là phiên bản triển khai của tôi.

 struct MyStack {
    phần tử int;
    int * CurrentMiniAddress;
 };

 void Push (giá trị int)
 {
    // Tạo cấu trúc cho bạn và điền giá trị
    MyStack S = new MyStack ();
    S-> phần tử = giá trị;

    if (Stack.Empty ())
    {    
        // Vì ngăn xếp trống, hãy trỏ CurrentMiniAddress đến chính nó
        S-> CurrentMiniAddress = S;

    }
    khác
    {
         // Ngăn xếp không trống

         // Lấy phần tử trên cùng. Không có Pop ()
         MyStack * TopElement = Stack.Top ();

         // Nhớ Luôn luôn phần tử TOP trỏ đến
         // phần tử tối thiểu trong toàn bộ ngăn xếp
         if (S-> phần tử CurrentMiniAddress-> phần tử)
         {
            // Nếu giá trị hiện tại là giá trị nhỏ nhất trong toàn bộ ngăn xếp
            // thì S trỏ đến chính nó
            S-> CurrentMiniAddress = S;
         }
             khác
             {
                 // Vì vậy, đây không phải là mức tối thiểu trong toàn bộ ngăn xếp
                 // Đừng lo, TOP đang giữ phần tử tối thiểu
                 S-> CurrentMiniAddress = TopElement-> CurrentMiniAddress;
             }

    }
        Stack.Add (S);
 }

 void Pop ()
 {
     if (! Stack.Empty ())
     {
        Stack.Pop ();
     }  
 }

 int GetMinimum (Ngăn xếp & ngăn xếp)
 {
       if (! stack.Empty ())
       {
            MyStack * Top = stack.top ();
            // Đỉnh luôn trỏ đến điểm nhỏ nhất
            return Top-> CurrentMiniAddress-> phần tử;
        }
 }

Tôi đồng ý, điều này yêu cầu một phần tử bổ sung trong cấu trúc của bạn. Nhưng điều này giúp loại bỏ việc tìm kiếm mức tối thiểu bất cứ khi nào chúng ta bật một phần tử.
Ganesh M

1
Vì vậy, không đáp ứng được các ràng buộc của câu hỏi, bạn đã nhận được công việc?
Pete Kirkham

0
#include<stdio.h>
struct stack
{
    int data;
    int mindata;
}a[100];

void push(int *tos,int input)
{
    if (*tos > 100)
    {
        printf("overflow");
        return;
    }
    (*tos)++;
    a[(*tos)].data=input;
    if (0 == *tos)
        a[*tos].mindata=input;
    else if (a[*tos -1].mindata < input)
        a[*tos].mindata=a[*tos -1].mindata;
    else
        a[*tos].mindata=input;
}

int pop(int * tos)
{
    if (*tos <= -1)
    {
        printf("underflow");
        return -1;
    }
    return(a[(*tos)--].data);
}
void display(int tos)
{
    while (tos > -1)
    {
        printf("%d:%d\t",a[tos].data,a[tos].mindata);
        tos--;
    }    
}

int min(int tos)
{
   return(a[tos].mindata);
}
int main()
{
int tos=-1,x,choice;
while(1)
{
    printf("press 1-push,2-pop,3-mindata,4-display,5-exit ");
    scanf("%d",&choice);
    switch(choice)
    {
    case 1: printf("enter data to push");
            scanf("%d",&x);
            push(&tos,x);
            break;
    case 2: printf("the poped out data=%d ",pop(&tos));
            break;
    case 3: printf("The min peeped data:%d",min(tos));
            break;
    case 4: printf("The elements of stack \n");
            display(tos);
            break;
    default: exit(0);
}
}

0

Tôi tìm thấy giải pháp này ở đây

struct StackGetMin {
  void push(int x) {
    elements.push(x);
    if (minStack.empty() || x <= minStack.top())
      minStack.push(x);
  }
  bool pop() {
    if (elements.empty()) return false;
    if (elements.top() == minStack.top())
      minStack.pop();
    elements.pop();
    return true;
  }
  bool getMin(int &min) {
    if (minStack.empty()) {
      return false;
    } else {
      min = minStack.top();
      return true;
    }
  }
  stack<int> elements;
  stack<int> minStack;
};

0
struct Node {
    let data: Int
    init(_ d:Int){
        data = d
    }
}

struct Stack {
    private var backingStore = [Node]()
    private var minArray = [Int]()

    mutating func push(n:Node) {
        backingStore.append(n)
        minArray.append(n.data)
        minArray.sort(>)
        minArray
    }

    mutating func pop() -> Node? {
        if(backingStore.isEmpty){
            return nil
        }

        let n = backingStore.removeLast()

        var found = false
        minArray = minArray.filter{
            if (!found && $0 == n.data) {
                found = true
                return false
            }
            return true
        }
        return n
    }

    func min() -> Int? {
        return minArray.last
    }
}

0
 class MyStackImplementation{
private final int capacity = 4;
int min;
int arr[] = new int[capacity];
int top = -1;

public void push ( int val ) {
top++;
if(top <= capacity-1){
    if(top == 0){
min = val;
arr[top] = val;
}
else if(val < min){
arr[top] = arr[top]+min;
min = arr[top]-min;
arr[top] = arr[top]-min;
}
else {
arr[top] = val;
}
System.out.println("element is pushed");
}
else System.out.println("stack is full");

}

 public void pop () {
top--;
   if(top > -1){ 

   min = arr[top];
}
else {min=0; System.out.println("stack is under flow");}

}
public int min(){
return min;
}

 public boolean isEmpty () {
    return top == 0;
}

public static void main(String...s){
MyStackImplementation msi = new MyStackImplementation();
msi.push(1);
msi.push(4);
msi.push(2);
msi.push(10);
System.out.println(msi.min);
msi.pop();
msi.pop();
msi.pop();
msi.pop();
msi.pop();
System.out.println(msi.min);

}
}

0
class FastStack {

    private static class StackNode {
        private Integer data;
        private StackNode nextMin;

        public StackNode(Integer data) {
            this.data = data;
        }

        public Integer getData() {
            return data;
        }

        public void setData(Integer data) {
            this.data = data;
        }

        public StackNode getNextMin() {
            return nextMin;
        }

        public void setNextMin(StackNode nextMin) {
            this.nextMin = nextMin;
        }

    }

    private LinkedList<StackNode> stack = new LinkedList<>();

    private StackNode currentMin = null;

    public void push(Integer item) {
        StackNode node = new StackNode(item);
        if (currentMin == null) {
            currentMin = node;
            node.setNextMin(null);
        } else if (item < currentMin.getData()) {
            StackNode oldMinNode = currentMin;
            node.setNextMin(oldMinNode);
            currentMin = node;
        }

        stack.addFirst(node);
    }

    public Integer pop() {
        if (stack.isEmpty()) {
            throw new EmptyStackException();
        }
        StackNode node = stack.peek();
        if (currentMin == node) {
            currentMin = node.getNextMin();
        }
        stack.removeFirst();
        return node.getData();
    }

    public Integer getMinimum() {
        if (stack.isEmpty()) {
            throw new NoSuchElementException("Stack is empty");
        }
        return currentMin.getData();
    }
}

0

Đây là Mã của tôi chạy với O (1). Ở đây tôi đã sử dụng cặp vectơ chứa giá trị được đẩy và cũng chứa giá trị tối thiểu lên đến giá trị được đẩy này.


Đây là phiên bản triển khai C ++ của tôi.

vector<pair<int,int> >A;
int sz=0; // to keep track of the size of vector

class MinStack
{
public:
    MinStack()
    {
        A.clear();
        sz=0;
    }

    void push(int x)
    {
        int mn=(sz==0)?x: min(A[sz-1].second,x); //find the minimum value upto this pushed value
        A.push_back(make_pair(x,mn));
        sz++; // increment the size
    }

    void pop()
    {
        if(sz==0) return;
        A.pop_back(); // pop the last inserted element
        sz--;  // decrement size
    }

    int top()
    {
        if(sz==0)   return -1;  // if stack empty return -1
        return A[sz-1].first;  // return the top element
    }

    int getMin()
    {
        if(sz==0) return -1;
        return A[sz-1].second; // return the minimum value at sz-1 
    }
};

0
    **The task can be acheived by creating two stacks:**



import java.util.Stack;
    /*
     * 
     * Find min in stack using O(n) Space Complexity
     */
    public class DeleteMinFromStack {

        void createStack(Stack<Integer> primary, Stack<Integer> minStack, int[] arr) {
    /* Create main Stack and in parallel create the stack which contains the minimum seen so far while creating main Stack */
            primary.push(arr[0]);
            minStack.push(arr[0]);

            for (int i = 1; i < arr.length; i++) {
                primary.push(arr[i]);
                if (arr[i] <= minStack.peek())// Condition to check to push the value in minimum stack only when this urrent value is less than value seen at top of this stack */
                    minStack.push(arr[i]);
            }

        }

        int findMin(Stack<Integer> secStack) {
            return secStack.peek();
        }

        public static void main(String args[]) {

            Stack<Integer> primaryStack = new Stack<Integer>();
            Stack<Integer> minStack = new Stack<Integer>();

            DeleteMinFromStack deleteMinFromStack = new DeleteMinFromStack();

            int[] arr = { 5, 5, 6, 8, 13, 1, 11, 6, 12 };
            deleteMinFromStack.createStack(primaryStack, minStack, arr);
            int mimElement = deleteMinFromStack.findMin(primaryStack, minStack);
    /** This check for algorithm when the main Stack Shrinks by size say i as in loop below */
            for (int i = 0; i < 2; i++) {
                primaryStack.pop();
            }

            System.out.println(" Minimum element is " + mimElement);
        }

    }
/*
here in have tried to add for loop wherin the main tack can be shrinked/expaned so we can check the algorithm */

Câu trả lời của Jon Skeet bổ sung thêm điều gì? Điều này sử dụng bao nhiêu không gian cho n về phía vô cùng (xem câu hỏi hoặc câu trả lời được liên kết)? Với một ngôn ngữ lập trình tuyên bố hỗ trợ OO, có vẻ thích hợp hơn để tạo một kiểu dữ liệu (không quá trừu tượng) / (chung chung) Class- MinStack? Tài liệu Java của Oracle khuyên bạn nên sử dụng Deque.
greybeard,

(Cảm ơn bạn đã đưa ra các gợi ý. (Các bình luận mã nên giải thích điều gì-để làm gì, như thế nào và tại sao - đề cập rằng một điều kiện là một điều kiện là không hữu ích. Một hoặc hai dòng đầu tiên tốt hơn không được thụt vào, nó đạt được, hiện tại, trong đó , bị thu hẹpmở rộng ...))
lọ

0

Một triển khai thực tế để tìm kiếm mức tối thiểu trong Ngăn xếp Đối tượng do Người dùng Thiết kế, có tên: Trường học

Stack sẽ lưu trữ các Trường trong Ngăn xếp dựa trên thứ hạng được chỉ định cho một trường trong khu vực cụ thể, chẳng hạn, findMin () cung cấp cho Trường nơi chúng tôi nhận được số lượng đơn đăng ký Tuyển sinh tối đa, điều này sẽ được xác định bởi bộ so sánh sử dụng thứ hạng được liên kết với các trường trong mùa trước.

The Code for same is below:


   package com.practical;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class CognitaStack {

    public School findMin(Stack<School> stack, Stack<School> minStack) {

        if (!stack.empty() && !minStack.isEmpty())
            return (School) minStack.peek();
        return null;
    }

    public School removeSchool(Stack<School> stack, Stack<School> minStack) {

        if (stack.isEmpty())
            return null;
        School temp = stack.peek();
        if (temp != null) {
            // if(temp.compare(stack.peek(), minStack.peek())<0){
            stack.pop();
            minStack.pop();
            // }

            // stack.pop();
        }
        return stack.peek();
    }

    public static void main(String args[]) {

        Stack<School> stack = new Stack<School>();
        Stack<School> minStack = new Stack<School>();

        List<School> lst = new LinkedList<School>();

        School s1 = new School("Polam School", "London", 3);
        School s2 = new School("AKELEY WOOD SENIOR SCHOOL", "BUCKINGHAM", 4);
        School s3 = new School("QUINTON HOUSE SCHOOL", "NORTHAMPTON", 2);
        School s4 = new School("OAKLEIGH HOUSE SCHOOL", " SWANSEA", 5);
        School s5 = new School("OAKLEIGH-OAK HIGH SCHOOL", "Devon", 1);
        School s6 = new School("BritishInter2", "Devon", 7);

        lst.add(s1);
        lst.add(s2);
        lst.add(s3);
        lst.add(s4);
        lst.add(s5);
        lst.add(s6);

        Iterator<School> itr = lst.iterator();
        while (itr.hasNext()) {
            School temp = itr.next();
            if ((minStack.isEmpty()) || (temp.compare(temp, minStack.peek()) < 0)) { // minStack.peek().equals(temp)
                stack.push(temp);
                minStack.push(temp);
            } else {
                minStack.push(minStack.peek());
                stack.push(temp);
            }

        }

        CognitaStack cogStack = new CognitaStack();
        System.out.println(" Minimum in Stack is " + cogStack.findMin(stack, minStack).name);
        cogStack.removeSchool(stack, minStack);
        cogStack.removeSchool(stack, minStack);

        System.out.println(" Minimum in Stack is "
                + ((cogStack.findMin(stack, minStack) != null) ? cogStack.findMin(stack, minStack).name : "Empty"));
    }

}

Đối tượng Trường cũng như sau:

package com.practical;

import java.util.Comparator;

public class School implements Comparator<School> {

    String name;
    String location;
    int rank;

    public School(String name, String location, int rank) {
        super();
        this.name = name;
        this.location = location;
        this.rank = rank;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((location == null) ? 0 : location.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + rank;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        School other = (School) obj;
        if (location == null) {
            if (other.location != null)
                return false;
        } else if (!location.equals(other.location))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (rank != other.rank)
            return false;
        return true;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public int getRank() {
        return rank;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public int compare(School o1, School o2) {
        // TODO Auto-generated method stub
        return o1.rank - o2.rank;
    }

}

class SchoolComparator implements Comparator<School> {

    public int compare(School o1, School o2) {
        return o1.rank - o2.rank;
    }

}

Ví dụ này bao gồm những điều sau: 1. Triển khai Ngăn xếp cho Đối tượng do Người dùng xác định, tại đây, Trường 2. Triển khai cho phương thức hashcode () và equals () bằng cách sử dụng tất cả các trường của Đối tượng được so sánh 3. Triển khai thực tế cho tình huống mà chúng ta rqeuire để có được phép toán Stack chứa theo thứ tự là O (1)


Không có thẻ ngôn ngữ cho câu hỏi này (hoàn toàn ngược lại language-agnostic:): vui lòng chỉ định những gì bạn sử dụng cho mã (và xóa các khoảng trống trước đó The Code for same is below:.) Điều này hỗ trợ stack.pop()như thế nào? (và push()?)
greybeard

0

Đây là cách triển khai PHP của những gì được giải thích trong câu trả lời của Jon Skeet là triển khai độ phức tạp không gian tốt hơn một chút để có được tối đa ngăn xếp trong O (1).

<?php

/**
 * An ordinary stack implementation.
 *
 * In real life we could just extend the built-in "SplStack" class.
 */
class BaseIntegerStack
{
    /**
     * Stack main storage.
     *
     * @var array
     */
    private $storage = [];

    // ------------------------------------------------------------------------
    // Public API
    // ------------------------------------------------------------------------

    /**
     * Pushes to stack.
     *
     * @param  int $value New item.
     *
     * @return bool
     */
    public function push($value)
    {
        return is_integer($value)
            ? (bool) array_push($this->storage, $value)
            : false;
    }

    /**
     * Pops an element off the stack.
     *
     * @return int
     */
    public function pop()
    {
        return array_pop($this->storage);
    }

    /**
     * See what's on top of the stack.
     *
     * @return int|bool
     */
    public function top()
    {
        return empty($this->storage)
            ? false
            : end($this->storage);
    }

    // ------------------------------------------------------------------------
    // Magic methods
    // ------------------------------------------------------------------------

    /**
     * String representation of the stack.
     *
     * @return string
     */
    public function __toString()
    {
        return implode('|', $this->storage);
    }
} // End of BaseIntegerStack class

/**
 * The stack implementation with getMax() method in O(1).
 */
class Stack extends BaseIntegerStack
{
    /**
     * Internal stack to keep track of main stack max values.
     *
     * @var BaseIntegerStack
     */
    private $maxStack;

    /**
     * Stack class constructor.
     *
     * Dependencies are injected.
     *
     * @param BaseIntegerStack $stack Internal stack.
     *
     * @return void
     */
    public function __construct(BaseIntegerStack $stack)
    {
        $this->maxStack = $stack;
    }

    // ------------------------------------------------------------------------
    // Public API
    // ------------------------------------------------------------------------

    /**
     * Prepends an item into the stack maintaining max values.
     *
     * @param  int $value New item to push to the stack.
     *
     * @return bool
     */
    public function push($value)
    {
        if ($this->isNewMax($value)) {
            $this->maxStack->push($value);
        }

        parent::push($value);
    }

    /**
     * Pops an element off the stack maintaining max values.
     *
     * @return int
     */
    public function pop()
    {
        $popped = parent::pop();

        if ($popped == $this->maxStack->top()) {
            $this->maxStack->pop();
        }

        return $popped;
    }

    /**
     * Finds the maximum of stack in O(1).
     *
     * @return int
     * @see push()
     */
    public function getMax()
    {
        return $this->maxStack->top();
    }

    // ------------------------------------------------------------------------
    // Internal helpers
    // ------------------------------------------------------------------------

    /**
     * Checks that passing value is a new stack max or not.
     *
     * @param  int $new New integer to check.
     *
     * @return boolean
     */
    private function isNewMax($new)
    {
        return empty($this->maxStack) OR $new > $this->maxStack->top();
    }

} // End of Stack class

// ------------------------------------------------------------------------
// Stack Consumption and Test
// ------------------------------------------------------------------------
$stack = new Stack(
    new BaseIntegerStack
);

$stack->push(9);
$stack->push(4);
$stack->push(237);
$stack->push(5);
$stack->push(556);
$stack->push(15);

print "Stack: $stack\n";
print "Max: {$stack->getMax()}\n\n";

print "Pop: {$stack->pop()}\n";
print "Pop: {$stack->pop()}\n\n";

print "Stack: $stack\n";
print "Max: {$stack->getMax()}\n\n";

print "Pop: {$stack->pop()}\n";
print "Pop: {$stack->pop()}\n\n";

print "Stack: $stack\n";
print "Max: {$stack->getMax()}\n";

// Here's the sample output:
//
// Stack: 9|4|237|5|556|15
// Max: 556
//
// Pop: 15
// Pop: 556
//
// Stack: 9|4|237|5
// Max: 237
//
// Pop: 5
// Pop: 237
//
// Stack: 9|4
// Max: 9

0

Đây là cách triển khai C ++ của Jon Skeets Answer . Nó có thể không phải là cách tối ưu nhất để triển khai, nhưng nó thực hiện chính xác những gì nó phải làm.

class Stack {
private:
    struct stack_node {
        int val;
        stack_node *next;
    };
    stack_node *top;
    stack_node *min_top;
public:
    Stack() {
        top = nullptr;
        min_top = nullptr;
    }    
    void push(int num) {
        stack_node *new_node = nullptr;
        new_node = new stack_node;
        new_node->val = num;

        if (is_empty()) {
            top = new_node;
            new_node->next = nullptr;

            min_top = new_node;
            new_node->next = nullptr;
        } else {
            new_node->next = top;
            top = new_node;

            if (new_node->val <= min_top->val) {
                new_node->next = min_top;
                min_top = new_node;
            }
        }
    }

    void pop(int &num) {
        stack_node *tmp_node = nullptr;
        stack_node *min_tmp = nullptr;

        if (is_empty()) {
            std::cout << "It's empty\n";
        } else {
            num = top->val;
            if (top->val == min_top->val) {
                min_tmp = min_top->next;
                delete min_top;
                min_top = min_tmp;
            }
            tmp_node = top->next;
            delete top;
            top = tmp_node;
        }
    }

    bool is_empty() const {
        return !top;
    }

    void get_min(int &item) {
        item = min_top->val;
    }
};

Và đây là trình điều khiển cho lớp học

int main() {
    int pop, min_el;
    Stack my_stack;

    my_stack.push(4);
    my_stack.push(6);
    my_stack.push(88);
    my_stack.push(1);
    my_stack.push(234);
    my_stack.push(2);

    my_stack.get_min(min_el);
    cout << "Min: " << min_el << endl;

    my_stack.pop(pop);
    cout << "Popped stock element: " << pop << endl;

    my_stack.pop(pop);
    cout << "Popped stock element: " << pop << endl;

    my_stack.pop(pop);
    cout << "Popped stock element: " << pop << endl;

    my_stack.get_min(min_el);
    cout << "Min: " << min_el << endl;

    return 0;
}

Đầu ra:

Min: 1
Popped stock element: 2
Popped stock element: 234
Popped stock element: 1
Min: 4

0

Chúng ta có thể làm điều này với độ phức tạp thời gian O (n) và không gian O (1), như sau:

class MinStackOptimized:
  def __init__(self):
      self.stack = []
      self.min = None

  def push(self, x): 
      if not self.stack:
          # stack is empty therefore directly add
          self.stack.append(x)
          self.min = x 
      else:
          """
          Directly add (x-self.min) to the stack. This also ensures anytime we have a 
          negative number on the stack is when x was less than existing minimum
          recorded thus far.
          """
          self.stack.append(x-self.min)
          if x < self.min:
              # Update x to new min
              self.min = x 

  def pop(self):
      x = self.stack.pop()
      if x < 0:
          """ 
          if popped element was negative therefore this was the minimum
          element, whose actual value is in self.min but stored value is what
          contributes to get the next min. (this is one of the trick we use to ensure
          we are able to get old minimum once current minimum gets popped proof is given
          below in pop method), value stored during push was:
          (x - self.old_min) and self.min = x therefore we need to backtrack
          these steps self.min(current) - stack_value(x) actually implies to
              x (self.min) - (x - self.old_min)
          which therefore gives old_min back and therefore can now be set
          back as current self.min.
          """
          self.min = self.min - x 

  def top(self):
      x = self.stack[-1]
      if x < 0:
          """ 
          As discussed above anytime there is a negative value on stack, this
          is the min value so far and therefore actual value is in self.min,
          current stack value is just for getting the next min at the time
          this gets popped.
          """
          return self.min
      else:
          """ 
          if top element of the stack was positive then it's simple, it was
          not the minimum at the time of pushing it and therefore what we did
          was x(actual) - self.min(min element at current stage) let's say `y`
          therefore we just need to reverse the process to get the actual
          value. Therefore self.min + y, which would translate to
              self.min + x(actual) - self.min, thereby giving x(actual) back
          as desired.
          """
          return x + self.min

  def getMin(self):
      # Always self.min variable holds the minimum so for so easy peezy.
      return self.min

0

Tôi nghĩ rằng bạn có thể đơn giản sử dụng LinkedList trong việc triển khai ngăn xếp của mình.

Lần đầu tiên bạn đẩy một giá trị, bạn đặt giá trị này làm đầu danh sách liên kết.

sau đó mỗi khi bạn đẩy một giá trị, nếu giá trị mới <head.data, hãy thực hiện một phép toán tiền và (có nghĩa là phần đầu trở thành giá trị mới)

nếu không, sau đó thực hiện một hoạt động nối thêm.

Khi bạn tạo một pop (), bạn kiểm tra xem min == linkedlist.head.data, nếu có, thì head = head.next;

Đây là mã của tôi.

public class Stack {

int[] elements;
int top;
Linkedlists min;

public Stack(int n) {
    elements = new int[n];
    top = 0;
    min = new Linkedlists();
}

public void realloc(int n) {
    int[] tab = new int[n];
    for (int i = 0; i < top; i++) {
        tab[i] = elements[i];
    }

    elements = tab;
}

public void push(int x) {
    if (top == elements.length) {
        realloc(elements.length * 2);
    }
    if (top == 0) {
        min.pre(x);
    } else if (x < min.head.data) {
        min.pre(x);
    } else {
        min.app(x);
    }
    elements[top++] = x;
}

public int pop() {

    int x = elements[--top];
    if (top == 0) {

    }
    if (this.getMin() == x) {
        min.head = min.head.next;
    }
    elements[top] = 0;
    if (4 * top < elements.length) {
        realloc((elements.length + 1) / 2);
    }

    return x;
}

public void display() {
    for (Object x : elements) {
        System.out.print(x + " ");
    }

}

public int getMin() {
    if (top == 0) {
        return 0;
    }
    return this.min.head.data;
}

public static void main(String[] args) {
    Stack stack = new Stack(4);
    stack.push(2);
    stack.push(3);
    stack.push(1);
    stack.push(4);
    stack.push(5);
    stack.pop();
    stack.pop();
    stack.pop();
    stack.push(1);
    stack.pop();
    stack.pop();
    stack.pop();
    stack.push(2);
    System.out.println(stack.getMin());
    stack.display();

}

 }

Có một dãy số. Trong một vòng lặp, nếu số chẵn, hãy bật hai mục. Đẩy số lượng và in tối thiểu.
greybeard

? Tôi không hiểu bình luận của bạn
Zok

Chúng ta có thể điều chỉnh phương pháp pop () để kiểm tra xem giá trị hàng đầu == 0, nếu như vậy, chúng tôi xóa danh sách liên kết bằng cách làm cho min.head = null, min.head.next = null
Zok

0
public class MinStack<E>{

    private final LinkedList<E> mainStack = new LinkedList<E>();
    private final LinkedList<E> minStack = new LinkedList<E>();
    private final Comparator<E> comparator;

    public MinStack(Comparator<E> comparator) 
    {
        this.comparator = comparator;
    }

    /**
     * Pushes an element onto the stack.
     *
     *
     * @param e the element to push
     */
    public void push(E e) {
        mainStack.push(e);
        if(minStack.isEmpty())
        {
            minStack.push(e);
        }
        else if(comparator.compare(e, minStack.peek())<=0)
        {
            minStack.push(e);
        }
        else
        {
            minStack.push(minStack.peek());
        }
    }

    /**
     * Pops an element from the stack.
     *
     *
     * @throws NoSuchElementException if this stack is empty
     */
    public E pop() {
       minStack.pop();
       return  mainStack.pop();
    }

    /**
     * Returns but not remove smallest element from the stack. Return null if stack is empty.
     *
     */
    public E getMinimum()
    {
        return minStack.peek();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Main stack{");
        for (E e : mainStack) {         
            sb.append(e.toString()).append(",");
        }
        sb.append("}");

        sb.append(" Min stack{");
        for (E e : minStack) {          
            sb.append(e.toString()).append(",");
        }
        sb.append("}");

        sb.append(" Minimum = ").append(getMinimum());
        return sb.toString();
    }

    public static void main(String[] args) {
        MinStack<Integer> st = new MinStack<Integer>(Comparators.INTEGERS);

        st.push(2);
        Assert.assertTrue("2 is min in stack {2}", st.getMinimum().equals(2));
        System.out.println(st);

        st.push(6);
        Assert.assertTrue("2 is min in stack {2,6}", st.getMinimum().equals(2));
        System.out.println(st);

        st.push(4);
        Assert.assertTrue("2 is min in stack {2,6,4}", st.getMinimum().equals(2));
        System.out.println(st);

        st.push(1);
        Assert.assertTrue("1 is min in stack {2,6,4,1}", st.getMinimum().equals(1));
        System.out.println(st);

        st.push(5);
        Assert.assertTrue("1 is min in stack {2,6,4,1,5}", st.getMinimum().equals(1));
        System.out.println(st);

        st.pop();
        Assert.assertTrue("1 is min in stack {2,6,4,1}", st.getMinimum().equals(1));
        System.out.println(st);

        st.pop();
        Assert.assertTrue("2 is min in stack {2,6,4}", st.getMinimum().equals(2));
        System.out.println(st);

        st.pop();
        Assert.assertTrue("2 is min in stack {2,6}", st.getMinimum().equals(2));
        System.out.println(st);

        st.pop();
        Assert.assertTrue("2 is min in stack {2}", st.getMinimum().equals(2));
        System.out.println(st);

        st.pop();
        Assert.assertTrue("null is min in stack {}", st.getMinimum()==null);
        System.out.println(st);
    }
}

0
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Solution 
{
    public class MinStack
    {
        public MinStack()
        {
            MainStack=new Stack<int>();
            Min=new Stack<int>();
        }

        static Stack<int> MainStack;
        static Stack<int> Min;

        public void Push(int item)
        {
            MainStack.Push(item);

            if(Min.Count==0 || item<Min.Peek())
                Min.Push(item);
        }

        public void Pop()
        {
            if(Min.Peek()==MainStack.Peek())
                Min.Pop();
            MainStack.Pop();
        }
        public int Peek()
        {
            return MainStack.Peek();
        }

        public int GetMin()
        {
            if(Min.Count==0)
                throw new System.InvalidOperationException("Stack Empty"); 
            return Min.Peek();
        }
    }
}

0

Thấy một giải pháp tuyệt vời tại đây: https://www.geeksforgeeks.org/design-a-stack-that-supports-getmin-in-o1-time-and-o1-extra-space/

Dưới đây là mã python tôi đã viết bằng cách làm theo thuật toán:

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

class MinStack:
    def __init__(self):
        self.head = None
        self.min = float('inf')

    # @param x, an integer
    def push(self, x):
        if self.head == None:
            self.head = Node(x)
            self.min = x
        else:
            if x >= self.min:
                n = Node(x)
                n.next = self.head
                self.head = n
            else:
                v = 2 * x - self.min
                n = Node(v)
                n.next = self.head
                self.head = n
                self.min = x

    # @return nothing
    def pop(self):
        if self.head:
            if self.head.value < self.min:
                self.min = self.min * 2 - self.head.value
            self.head = self.head.next

    # @return an integer
    def top(self):
        if self.head:
            if self.head.value < self.min:
                self.min = self.min * 2 - self.head.value
                return self.min
            else:
                return self.head.value
        else:
            return -1

    # @return an integer
    def getMin(self):
        if self.head:
            return self.min
        else:
            return -1

0

Để getMin các phần tử từ Stack. Chúng ta phải sử dụng Hai ngăn xếp .ie Ngăn xếp s1 và Ngăn xếp s2.

  1. Ban đầu, cả hai ngăn xếp đều trống, vì vậy hãy thêm các phần tử vào cả hai ngăn xếp

--------------------- Gọi đệ quy Bước 2 đến 4 -----------------------

  1. nếu Phần tử mới được thêm vào ngăn xếp s1. Sau đó bật các phần tử từ ngăn xếp s2

  2. so sánh các chất rửa giải mới với s2. cái nào nhỏ hơn thì đẩy tới s2.

  3. bật ra từ ngăn xếp s2 (chứa phần tử tối thiểu)

Mã trông giống như:

package Stack;
import java.util.Stack;
public class  getMin 
{  

        Stack<Integer> s1= new Stack<Integer>();
        Stack<Integer> s2 = new Stack<Integer>();

        void push(int x)
        {
            if(s1.isEmpty() || s2.isEmpty())

            {
                 s1.push(x);
                 s2.push(x);
            }
            else
            {

               s1. push(x);
                int y = (Integer) s2.pop();
                s2.push(y);
                if(x < y)
                    s2.push(x);
                        }
        }
        public Integer pop()
        {
            int x;
            x=(Integer) s1.pop();
            s2.pop();
            return x;

        }
    public  int getmin()
        {
            int x1;
            x1= (Integer)s2.pop();
            s2.push(x1);
            return x1;
        }

    public static void main(String[] args) {
        getMin s = new getMin();
            s.push(10);
            s.push(20);
            s.push(30);
            System.out.println(s.getmin());
            s.push(1);
            System.out.println(s.getmin());
        }

}

-1

Tôi nghĩ rằng chỉ có hoạt động đẩy chịu đựng, là đủ. Việc triển khai của tôi bao gồm một chồng các nút. Mỗi nút chứa mục dữ liệu và cũng là mục tối thiểu vào thời điểm đó. Mức tối thiểu này được cập nhật mỗi khi thực hiện thao tác đẩy.

Dưới đây là một số điểm để hiểu:

  • Tôi đã triển khai ngăn xếp bằng Danh sách được Liên kết.

  • Đầu con trỏ luôn trỏ đến mục được đẩy cuối cùng. Khi không có mục nào trong đỉnh ngăn xếp đó là NULL.

  • Khi một mục được đẩy, một nút mới được cấp phát có một con trỏ tiếp theo trỏ đến ngăn xếp trước đó và đỉnh được cập nhật để trỏ đến nút mới này.

Chỉ có sự khác biệt với việc triển khai ngăn xếp bình thường là trong quá trình đẩy, nó cập nhật một thành viên tối thiểu cho nút mới.

Vui lòng xem mã được triển khai trong C ++ cho mục đích trình diễn.

/*
 *  Implementation of Stack that can give minimum in O(1) time all the time
 *  This solution uses same data structure for minimum variable, it could be implemented using pointers but that will be more space consuming
 */

#include <iostream>
using namespace std;

typedef struct stackLLNodeType stackLLNode;

struct stackLLNodeType {
    int item;
    int min;
    stackLLNode *next;
};

class DynamicStack {
private:
    int stackSize;
    stackLLNode *top;

public:
    DynamicStack();
    ~DynamicStack();
    void push(int x);
    int pop();
    int getMin();
    int size() { return stackSize; }
};

void pushOperation(DynamicStack& p_stackObj, int item);
void popOperation(DynamicStack& p_stackObj);

int main () {
    DynamicStack stackObj;

    pushOperation(stackObj, 3);
    pushOperation(stackObj, 1);
    pushOperation(stackObj, 2);
    popOperation(stackObj);
    popOperation(stackObj);
    popOperation(stackObj);
    popOperation(stackObj);
    pushOperation(stackObj, 4);
    pushOperation(stackObj, 7);
    pushOperation(stackObj, 6);
    popOperation(stackObj);
    popOperation(stackObj);
    popOperation(stackObj);
    popOperation(stackObj);

    return 0;
}

DynamicStack::DynamicStack() {
    // initialization
    stackSize = 0;
    top = NULL;
}

DynamicStack::~DynamicStack() {
    stackLLNode* tmp;
    // chain memory deallocation to avoid memory leak
    while (top) {
        tmp = top;
        top = top->next;
        delete tmp;
    }
}

void DynamicStack::push(int x) {
    // allocate memory for new node assign to top
    if (top==NULL) {
        top = new stackLLNode;
        top->item = x;
        top->next = NULL;
        top->min = top->item;
    }
    else {
        // allocation of memory
        stackLLNode *tmp = new stackLLNode;
        // assign the new item
        tmp->item = x;
        tmp->next = top;

        // store the minimum so that it does not get lost after pop operation of later minimum
        if (x < top->min)
            tmp->min = x;
        else
            tmp->min = top->min;

        // update top to new node
        top = tmp;
    }
    stackSize++;
}

int DynamicStack::pop() {
    // check if stack is empty
    if (top == NULL)
        return -1;

    stackLLNode* tmp = top;
    int curItem = top->item;
    top = top->next;
    delete tmp;
    stackSize--;
    return curItem;
}

int DynamicStack::getMin() {
    if (top == NULL)
        return -1;
    return top->min;
}
void pushOperation(DynamicStack& p_stackObj, int item) {
    cout<<"Just pushed: "<<item<<endl;
    p_stackObj.push(item);
    cout<<"Current stack min: "<<p_stackObj.getMin()<<endl;
    cout<<"Current stack size: "<<p_stackObj.size()<<endl<<endl;
}

void popOperation(DynamicStack& p_stackObj) {
    int popItem = -1;
    if ((popItem = p_stackObj.pop()) == -1 )
        cout<<"Cannot pop. Stack is empty."<<endl;
    else {
        cout<<"Just popped: "<<popItem<<endl;
        if (p_stackObj.getMin() == -1)
            cout<<"No minimum. Stack is empty."<<endl;
        else
            cout<<"Current stack min: "<<p_stackObj.getMin()<<endl;
        cout<<"Current stack size: "<<p_stackObj.size()<<endl<<endl;
    }
}

Và đầu ra của chương trình sẽ như thế này:

Just pushed: 3
Current stack min: 3
Current stack size: 1

Just pushed: 1
Current stack min: 1
Current stack size: 2

Just pushed: 2
Current stack min: 1
Current stack size: 3

Just popped: 2
Current stack min: 1
Current stack size: 2

Just popped: 1
Current stack min: 3
Current stack size: 1

Just popped: 3
No minimum. Stack is empty.
Current stack size: 0

Cannot pop. Stack is empty.
Just pushed: 4
Current stack min: 4
Current stack size: 1

Just pushed: 7
Current stack min: 4
Current stack size: 2

Just pushed: 6
Current stack min: 4
Current stack size: 3

Just popped: 6
Current stack min: 4
Current stack size: 2

Just popped: 7
Current stack min: 4
Current stack size: 1

Just popped: 4
No minimum. Stack is empty.
Current stack size: 0

Cannot pop. Stack is empty.

-1
public interface IMinStack<T extends Comparable<T>> {
  public void push(T val);
  public T pop();
  public T minValue();
  public int size();
}

import java.util.Stack;

public class MinStack<T extends Comparable<T>> implements IMinStack<T> {
  private Stack<T> stack = new Stack<T>();
  private Stack<T> minStack = new Stack<T>();

  @Override
  public void push(T val) {
    stack.push(val);
    if (minStack.isEmpty() || val.compareTo(minStack.peek()) < 0)
        minStack.push(val);
  }

  @Override
  public T pop() {
    T val = stack.pop();
    if ((false == minStack.isEmpty())
            && val.compareTo(minStack.peek()) == 0)
        minStack.pop();
    return val;
  }

  @Override
  public T minValue() {
    return minStack.peek();
  }

  @Override
  public int size() {
    return stack.size();
  }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.