最近我被问到一个问题,在一个单独的链表中,我们如何在一次迭代中进入列表的中间位置。
A --> B --> C --> D (even nodes)
为此它应该返回指向B的地址
A --> B --> C (odd nodes)
对此也应该返回指向B的地址
有一个解决方案是采取两个指针,一个移动一次,其他移动两次,但它似乎没有在这里工作
LinkedList p1,p2;
while(p2.next != null)
{
p1 = p1.next;
p2 = p2.next.next;
}
System.out.print("middle of the node" + p1.data); //This does not give accurate result in odd and even
如果有人以前这样做过,请帮忙。
答案 0 :(得分:6)
基本算法是
0 拿两个指针
1 同时指向第一个节点
2 首先使用两个节点递增,如果成功,则首先递增,然后再次遍历一个节点
3 当第二个到达结束时,第一个将在中间。
更新:
它肯定会在奇数的情况下工作,即使你需要再检查一个条件,如果第一个点允许移动 next 而不是旁边接下来然后两个指针都在中间,您需要决定将哪个作为中间
答案 1 :(得分:5)
除非成功高级p2两次,否则无法前进p1;否则,如果列表长度为2,则最终都会指向末尾(并且您指示甚至长度列表应该朝向开头舍入)。
所以:
while ( p2.next != null ) {
p2 = p2.next;
if (p2.next != null) {
p2 = p2.next;
p1 = p1.next;
}
}
答案 2 :(得分:1)
我知道你已经接受了答案,但这整个问题听起来像是一种聪明的练习,而不是试图获得正确的解决方案。当你能在O(n / 2)中做到时,为什么要用O(n)做某事?
编辑:这用于断言O(1)性能,这根本就不正确。感谢ysth指出这一点。
在实践中,您将在零迭代中执行此操作:
LinkedList list = ...
int size = list.size();
int middle = (size / 2) + (size % 2 == 0 ? 0 : 1) - 1; //index of middle item
Object o = list.get(middle); //or ListIterator it = list.listIterator(middle);
答案 3 :(得分:0)
采取两个指针和一个移动一半的速率的解决方案应该工作正常。最有可能的不是解决方案,而是您的实际实施问题。发布有关实施的更多详细信息。
答案 4 :(得分:0)
static ListElement findMiddle(ListElement head){
ListElement slower = head;
ListElement faster = head;
while(faster.next != null && faster.next.next !=null ){
faster = faster.next.next;
slower = slower.next;
}
return slower;
}
答案 5 :(得分:0)
public static Node middle(Node head){
Node slow=head,fast=head;
while(fast!=null& fast.next!=null && fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
}
if(fast!=null && fast.next!=null){
slow=slow.next;
}
return slow;
}
答案 6 :(得分:0)
public ListNode middleNode(ListNode head) {
if(head == null) return head;
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}