how to find the middle of the linked list when we are not informed of its size and it must be performed using only one loop and only one pointer.
+8
A:
Node *m,*e,*head; /* head is given */
m=e=head;
while(e) {
e=e->next;
if (e) {
e=e->next;
m=m->next;
}
}
/* now m is the middle node */
Sorry, I had to use 2 pointers :)
Adding this to your answer, because a minor tweak reduces the number of pointers to 1. I hope you don't mind:
Node m,*e,*head; /* head is given */
e = head;
if (e) m = *e;
while(e) {
e = e->next;
if (e) {
e = e->next;
m = *(m.next);
}
}
/* now m is the middle node */
wrang-wrang
2009-11-17 04:36:46
Well, it's not challenging at all when you cheat.
rlbond
2009-11-17 04:39:19
@rlbond: It is still very clever, though.
Thilo
2009-11-17 04:45:16
@rlbond: if you think of a better solution, propose it instead of grumbling, it seems to me the most logical solution. Though obviously the middle node in case of an even number of nodes is quite debatable.
Matthieu M.
2009-11-17 13:53:02
@Matthieu, but the problem was explicitly posed as requiring that it "must be performed using only one loop and only one pointer." It's nice and clean, but not a solution for the problem as posed in the question.
Suppressingfire
2009-11-17 15:39:35
I'm happy to have Mike's code stay, but I have to point out that the Node m contains a pointer (m.next), so it's a technicality :)
wrang-wrang
2009-12-03 12:53:29
+2
A:
Well, it's sort of a hack, since it's functionally equivalent to 2 loops. But still, it is only 1 loop.
Node* middle(Node* const begin)
{
Node* current = begin;
bool size_known = false;
int size = 0;
while (true)
{
if (!size_known)
{
if (current)
{
++size;
current = current->next;
}
else
{
current = begin;
size_known = true;
}
}
else
{
if (size <= 1)
return current;
current = current->next;
size -= 2;
}
}
}
rlbond
2009-11-17 04:44:10
How is using an extra bool and an extra int different from using an extra pointer?
Thilo
2009-11-17 04:48:01
+11
A:
How about
LinkedList * llist = getLList(); // the linked list
Node * node = llist.head;
while ( node ) {
node = node.next;
if ( node ) {
node = node.next;
llist.remove( llist.head );
}
}
// now llist.head is (er, um... was) the middle node.
// hope you didn't need the rest of the list.
Paul Hanbury
2009-11-17 04:50:26
But you are using two pointers. Definitely "e" and definitely "head". wrang-wrang's solution seems to me just the same...I think there is no answer to this question. You just can't handle the L1 list with one pointer (because when you move it, you loose your head (well... list head))
SadSido
2009-11-17 08:52:56
@SadSido: Obviously, if I have a linked list, I have a bunch of pointers, including the head. I assumed that the question meant one pointer, in addition to those already in the the list.
Paul Hanbury
2009-11-17 13:06:14
@SadSido: Yes, I do realize that I am destroying the list in the process. However, since the requirements were so unnatural, I didn't think the solution needed to be extra-resilient.
Paul Hanbury
2009-11-17 13:11:34
+1
A:
see my code. it works on my FC9 x86_64 correctly, the function "middle()" is that what you want:
static struct node *middle(struct node *head)
{
struct node *mid = head;
int flag = 0;
while (NULL != head) {
head = head->next;
flag = !flag;
if (flag) {
mid = mid->next;
}
}
return mid;
}
EDIT: remove code except the middle().
EffoStaff Effo
2009-11-17 04:54:47
A:
Iterate over your list using the provided head pointer and increment your one allowed pointer (I assume from your ambiguously-worded question that you're allowed one pointer besides the one that was passed in) once for every two increments of the head pointer.
Node* middle( Node* head )
{
Node* middle = head;
while (head != NULL) {
head = head->next;
if (head->next != NULL) {
head = head->next;
middle = middle->next;
}
}
return middle;
}
There are edge cases ignored here (like what's the middle of a list with an even number of elements).
Rob Pelletier
2009-11-17 05:03:08