数据结构和算法中最受欢迎的问题之一,通常是电话面试中提出的问题。
数据结构和算法中最受欢迎的问题之一,通常是电话面试中提出的问题。
Answers:
通过作弊,并同时并行进行两遍。但是我不知道招聘人员是否会喜欢这样。
可以在一个链接列表上完成,这是一个不错的技巧。列表上有两个指针,其中一个指针是双倍速度。当一个快结束时,另一个快到一半。
如果它不是双向链接列表,则可以只计算并使用一个列表,但这在最坏的情况下需要将内存加倍,并且如果列表太大而无法存储在内存中,它将根本无法工作。
一个简单,几乎愚蠢的解决方案是每两个节点增加中间节点
function middle(start) {
var middle = start
var nextnode = start
var do_increment = false;
while (nextnode.next != null) {
if (do_increment) {
middle = middle.next;
}
do_increment = !do_increment;
nextnode = nextnode.next;
}
return middle;
}
阐述亨德里克的答案
如果是双链表,则从两端进行迭代
function middle(start, end) {
do_advance_start = false;
while(start !== end && start && end) {
if (do_advance_start) {
start = start.next
}
else {
end = end.prev
}
do_advance_start = !do_advance_start
}
return (start === end) ? start : null;
}
给定 [1, 2, 3] => 2
1, 3
1, 2
2, 2
给定 [1, 2] => 1
1, 2
1, 1
给定 [1] => 1
给定 [] => null
创建一个动态数组,其中数组的每个元素都是从头开始以遍历顺序指向列表中每个节点的指针。创建一个初始化为1的整数,该整数跟踪您访问过的节点数(每次访问新节点时该节点递增)。到达最后时,您知道列表的大小,并且每个节点都有一个有序的指针数组。最后,将列表的大小除以2(对于基于0的索引,将其减去1)并获取保存在该数组索引中的指针;如果列表的大小为奇数,则可以选择要返回的元素(我仍将返回第一个元素)。
这是一些可以理解这一点的Java代码(即使动态数组的想法有点奇怪)。我会提供C / C ++,但在那方面我很生疏。
public Node getMiddleNode(List<Node> nodes){
int size = 1;
//add code to dynamically increase size if at capacity after adding
Node[] pointers = new Node[10];
for (int i = 0; i < nodes.size(); i++){
//remember to dynamically allocate more space if needed
pointers[i] = nodes.get(i);
size++;
}
return pointers[(size - 1)/2];
}
递归是否被视为不只一次通过?
将列表遍历到末尾,并通过引用传递一个整数计数。在每个级别上对该值进行本地复制以供以后参考,并增加进入下一个调用的参考计数。
在最后一个节点上,将计数除以二,然后将结果截断/ floor()(如果您希望只有两个元素的情况下第一个节点为“中间”)或舍入(如果希望第二个节点为中间”)。适当使用基于零或一的索引。
展开,将引用计数与本地副本(这是节点的编号)匹配。如果相等,则返回该节点。否则,返回从递归调用返回的节点。
。
还有其他方法可以做到这一点。其中一些可能不那么麻烦(我以为我看到有人说将其读入数组并使用数组长度来确定中间值-荣誉)。但坦率地说,没有很好的答案,因为这是一个愚蠢的面试问题。第一,仍然使用链表(支持意见);第二,找到中间节点是一个随意的,学术性的练习,在现实生活中没有价值。第三,如果我真的需要知道中间节点,那么我的链表将公开一个节点数。与每次我想要中间节点时浪费时间遍历整个列表相比,维护该属性要容易得多。最后,四个,每个面试官都会喜欢或拒绝不同的答案-一位面试官认为这很狡猾,另一位面试官则认为这很荒谬。
我几乎总是用更多的问题回答面试问题。如果我遇到这样的问题(我从未遇到过),我会问(1)您在此链表中存储了什么,并且如果确实有需要,是否有更合适的结构可以有效地访问中间节点; (2)我的约束是什么?如果内存不是问题(例如数组答案),我可以使速度更快,但是如果访问员认为增加内存浪费,我会感到沮丧。(3)我将使用哪种语言开发?我所了解的几乎每一种现代语言都有内置的类来处理链接列表,而这些链接列表使遍历列表不再必要-为什么要重新发明一些已被语言开发人员调整以提高效率的东西?
通过使用2个指针。在每个迭代中增加一个,在第二个迭代中增加另一个。当第一个指针指向链表的末尾时,第二个指针将指向链表的中间模式。