定义栈的数据结构,要求添加一个min函数,能够得到栈的最小(大)元素。
要求函数min、push以及pop的时间复杂度都是O(1)。
解析:本题要求自定义栈结构及操作(push,pop等),无论入栈多少个元素,元素的具体值为多少,在pop(n>=0次)操作后都可以通过自定义的FinMin()找到当前栈中的最小(大)元素。
思路:借助辅助栈。栈stack 用于存储入栈元素,栈minStack 用于记录stack栈中最小元素在stack中的位置。
(1).第一个将要进入stack栈的元素同样也要进入到minSstck栈中
(2).此后,元素直接进入stack栈中,而 进入minStack栈的元素arg要满足 arg < stack[minStack[minStack.Count - 1]]条件。
因此可以写成 :
stack.push(arg);
if( minStack.IsEmpty() || arg < stack[minStack[minStack.Count - 1] ] ) { minStack.Push( stack.Count - 1 ) } ( 以上为伪码,具体语言具体实现)
这样一来,minStack中记录的是stack当前栈中元素的最小值(第一次出现)在该栈中的位置。
那么stack中有元素出栈之后,minStack是如何保持栈顶元素为stack栈中元素最小值的呢?
每当 stack有元素a出栈时,就要和minStack中记录的对应位置的值进行比较,若a大于等于minStack中记录位置的值,则只管出栈;若是小于则
minStack也要执行Pop操作。那么此时的minStack栈顶元素即为 stack栈中的最小值对应的坐标。
具体见原文: http://blog.youkuaiyun.com/v_july_v/article/details/6126406 第二题;
以下为c#实现代码(初学c#,实现的很憋足,望指正):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace MS100
{
class Program
{
public class FindMin<T>
{
private List<int> minStack = new List<int>();
private List<T> stack = new List<T>();
public void Push(T arg)
{
stack.Add(arg);
if(minStack.Count == 0 || CompareToInt(arg , stack[minStack.Count - 1]) < 0)
{
minStack.Add(stack.Count - 1);
}
}
public void Pop()
{
if ( CompareToInt(stack[stack.Count - 1] , stack[minStack[minStack.Count - 1]]) == 0 )
{
stack.RemoveAt(stack.Count - 1);
minStack.RemoveAt(minStack.Count - 1);
}
}
public T min()
{
return stack[minStack[minStack.Count - 1]];
}
public int CompareToInt(T arg1 , T arg2)
{
object larg = (object)arg1;
object rarg = (object)arg2;
return ((int)larg).CompareTo((int)rarg);
}
}
static void Main(string[] args)
{
FindMin<int> a = new FindMin<int>();
a.Push(2);
a.Push(3);
a.Push(6);
a.Push(1);
Console.WriteLine(a.min().ToString());
a.Pop();
Console.WriteLine(a.min().ToString());
Console.ReadKey();
}
}
参考资料:http://blog.youkuaiyun.com/v_july_v/article/details/6126406
希望能帮到像我一样的初学者。