我在一次采访中被问到这个问题。问题是我会得到一个堆栈,并且必须在堆栈的中间位置找到元素。“top”索引不可用(这样你就不会弹出()top / 2次并返回答案)。假设当pop()返回-1时你将到达堆栈的底部。不要使用任何其他数据结构。
例如:
stack index
-----
2 nth element
3
99
.
1 n/2 th element
.
-1 bottom of the stack(0th index)
答案:1(我的意思不是中位数。找到中间位置的元素)
递归是唯一的方法吗?
谢谢,
PSY
答案 0 :(得分:13)
遍历堆栈,计算深度,并在返回途中返回相应的元素。
int middle(stack* s, int n, int* depth) {
if (stack_empty(s)) {
*depth = n;
return 0; //return something, doesn't matter..
}
int val = stack_pop(s);
int res = middle(s, n+1, depth);
stack_push(s, val);
if (n == *depth/2)
return val;
return res;
}
int depth;
middle(&stack, 0, &depth);
注意:是的,递归是唯一的方法。不知道堆栈的深度意味着你必须将这些值存储在某个地方。
答案 1 :(得分:6)
递归绝不是唯一的方法;)
但是,递归为您提供了隐含的附加堆栈(即函数参数和局部变量),并且看起来您需要一些额外的存储来存储遍历的元素,在这种情况下,看起来递归可能是给定的唯一方法那个约束。
答案 2 :(得分:0)
这是一个解决方案:取两个指针,一次推进其中一个步骤(快速),另一个一次只推进一步(慢速)。如果快速到达底部,则返回指向中间索引的慢速指针。不需要递归。
int * slow = stack;
int * fast = stack;
while(1) {
if(STACK_BOTTOM(fast)) return slow;
fast--;
if(STACK_BOTTOM(fast)) return slow;
slow--;
fast--;
}
答案 3 :(得分:0)
递归似乎是唯一的方法。如果在弹出过程中尝试使用快速和慢速指针概念,则需要将值存储在某处并且违反不需要其他数据结构的要求。
答案 4 :(得分:0)
此问题标有c
,因此对于c编程语言,我同意递归是唯一的方法。但是,如果支持第一类匿名函数,则可以在不递归的情况下解决它。一些伪代码(使用Haskell的lambda语法):
n = 0
f = \x -> 0 # constant function that always returns 0
while (not stack_empty) do
x = pop
n = n+1
f = \a -> if (a == n) then x else f(a)
middle = f(n/2) # middle of stack
# stack is empty, rebuilt it up to middle if required
for x in (n .. n/2) do push(f(x))
请注意:在while循环期间,f
没有(递归)调用。 else分支中的f(a)
仅用于构造一个新的(!)函数,该函数再次被称为f
。
假设堆栈有3个元素10,20,30(从下到上)这基本上构造了lambda
(\a -> if a==1
then 30
else (\b -> if b==2
then 20
else (\c -> if c==3
then 10
else (\d -> 0)(c)
)
(b)
)
(a)
)
或更具可读性
f(x) = if x==1 then 30 else (if x==2 then 20 else (if x==3 then 10 else 0))
答案 5 :(得分:0)
“......不要使用任何其他数据结构。”
然后该任务无法解决,因为您需要一些存储弹出数据的位置。你需要另一个用于递归的堆栈,它也是一个数据结构。禁止任何数据结构并允许递归是没有意义的。