0

I was solving a Leetcode problem regarding the linked list. I am wondering why a return value has to be head instead of result in below code.

Input: 1->1->2
Output: 1->2

If I return a result, output is 2.

public static ListNode deleteDuplicates(ListNode head) {
    ListNode result = head;

    if (head == null)
        return head;
    // System.out.println(listNodetoString(result));

    while (result.next != null) {
        if (result.val == result.next.val)
            result.next = result.next.next;
        else
            result = result.next;
    }
    return head;
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
FutureDev
  • 27
  • 5
  • 1
    We have to return the head to get the complete List after deleting the duplicates – Shashank Gupta Jun 17 '19 at 18:43
  • 1
    Because returning the tail of a linked list isn't helpful? – azurefrog Jun 17 '19 at 18:43
  • since you do ListNode result = head; result is just another reference to head and lines result.next= result.next.next is the same as you would use head.next, you can spare result variable anddo everything with head – user8426627 Jun 17 '19 at 18:43
  • 4
    It's the sort of method that doesn't really need a return value at all, IMHO, but returning the head lets you then turn around and chain other methods. Returning the result is kind of random. – Joseph Larson Jun 17 '19 at 18:44
  • 2
    `result` is a poor and, as we can see, misleading name. It's not the result of anything, it's just a temporary variable used to traverse the list. Better names would be `node` or `temp`. – John Kugelman Jun 17 '19 at 18:45
  • As an aside: "*`if (result.val == result.next.val)`*" - if `val` is not a primitive, this will get you in some trouble. See [this question](https://stackoverflow.com/questions/7520432/what-is-the-difference-between-and-equals-in-java) for details. – Turing85 Jun 17 '19 at 18:47

2 Answers2

3

If I understood well your question what is troubling you is mutability (and pointers)
Given your method:

public static ListNode deleteDuplicates(ListNode head) {
    ListNode result = head;

    if (head == null)
        return head;
    // System.out.println(ListNodetoString(result));

    while (result.next != null) {
        if (result.val == result.next.val)
            result.next = result.next.next;
        else
            result = result.next;
    }
    return head;
}

(simplified response),
the memory, at the beginning of the method, contains just the head pointer to the list:

         1-next->1-next->2
         ↑
head:----┘

when you do:

ListNode result = head;

you're creating a pointer to the same value as head is pointing, like:

         1-next->1-next->2
         ↑
head:----┘
result:--┘

Then you start iterating the list, and the branches of the if condition cause different effects.
When result.val == result.next.val is true you modify the internal state of the ListNode using

result.next = result.next.next;

What it does, is changing the pointer of the list, as you are referencing the field .next of the value whom result is pointing, like:

                 1-next--┐
                         ↓ 
         1-----next----->2
         ↑
head:----┘
result:--┘

as result.next was changed, the 2nd node (the 1 in first line) is not referenced anymore by any pointer. Then your while start again, having the if condition false, at this point the method does:

result = result.next;

In this way you are changing what result is pointing to, like:

           1-next┐
                 ↓ 
         1-next->2
         ↑       ↑
head:----┘       |
result:----------┘

So when you return head you are returning the value head is pointing to, the first element of the list. Meanwhile during the iteration result change each time the if return a false, going on if your initial list was:

1-next->1-next->2-next->3

The next iteration would change result again like:

           1-next┐
                 ↓ 
         1-next->2-next->3
         ↑               ↑
head:----┘               |
result:------------------┘

But head always remain to the top element.
The fact is that you don't need a return value, for what I understood from your code, it would works also as:

public static void deleteDuplicates(ListNode head) {
    ListNode result = head;

    if (head == null)
        return;
    // System.out.println(listNodetoString(result));

    while (result.next != null) {
        if (result.val == result.next.val)
            result.next = result.next.next;
        else
            result = result.next;
    }
}

Then you can try it with something like:

ListNode list = new ListNode(1, new ListNode(1, new ListNode(2, null)));
deleteDuplicates(list);
System.out.println(listNodetoString(list));

That's because in this way list is pointing also to the first value of the list, so at the beginning of the method the memory is something like:

list:----┐
         ↓
         1-next->1-next->2
         ↑
head:----┘
rascio
  • 8,968
  • 19
  • 68
  • 108
0

Clean method for that is :

 public static ListNode deleteDuplicateas(ListNode head) {

    while (head != null) {
        if (head.val == head.next.val)
            head.next = head.next.next;
        else
            head= head.next;
    }
}
user8426627
  • 903
  • 1
  • 9
  • 19
  • 2
    `if (head.val == head.next.val)` is still a smell. Furthermore, this code will not compile since a return statement is missing. And speaking of clean code... I wonder why a method called `delecteDuplicateas(...)` needs a return value and what is actually returned... – Turing85 Jun 17 '19 at 18:49
  • That doesn't even compile. – Robert Jun 18 '19 at 17:07
  • come on just make void output, is not big deal – user8426627 Jun 18 '19 at 17:18