1.3.45 #
解答 #
书上已经给出了思路,简单说明一下。
第一问是给定输入判断是否会下溢出,只要记录栈中元素的数量即可,一旦为负数则返回 true。
第二问是给定输出判断是否可能。
对于输出序列中的每一个数,如果栈顶为空或者栈顶数字小于当前输出序列的数,那么就从输入序列中输入数字,直到栈顶数字和当前输出序列中的数字相等。
如果当前输出序列中的数字和栈顶元素相等,从栈中弹出相应元素。
最后如果栈为空则可能,否则不可能。
可以结合习题 1.3.3 的解答查看。
通用解法见下一题。
代码 #
// 给定输入序列,判断是否会出现下溢出。
var input = "- 0 1 2 3 4 5 6 7 8 9 - - - - - - - - -";
Console.WriteLine(IsUnderflow(input.Split(' '))); //True
input = "0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -";
Console.WriteLine(IsUnderflow(input.Split(' '))); //False
// 给定输出序列,判定是否可能。
int[] output = { 4, 3, 2, 1, 0, 9, 8, 7, 6, 5 };
Console.WriteLine(IsOutputPossible(output)); //True
output = new[] { 4, 6, 8, 7, 5, 3, 2, 9, 0, 1 };
Console.WriteLine(IsOutputPossible(output)); //False
static bool IsUnderflow(string[] input)
{
// 记录栈中元素数量,如果元素数量小于 0 则会出现下溢出。
var count = 0;
foreach (var s in input)
{
if (count < 0)
{
return true;
}
if (s.Equals("-"))
{
count--;
}
else
{
count++;
}
}
return false;
}
static bool IsOutputPossible(int[] output)
{
var input = 0;
var n = output.Length;
var stack = new Stack<int>();
foreach (var i in output)
{
// 如果栈为空,则从输入序列中压入一个数。
if (stack.IsEmpty())
{
stack.Push(input);
input++;
}
// 如果输入序列中的所有数都已经入栈过了,跳出循环。
if (input == n && stack.Peek() != i)
{
break;
}
// 如果输出序列的下一个数不等于栈顶的数,那么就从输入序列中压入一个数。
while (stack.Peek() != i && input < n)
{
stack.Push(input);
input++;
}
// 如果栈顶的数等于输出的数,弹出它。
if (stack.Peek() == i)
{
stack.Pop();
}
}
return stack.IsEmpty();
}