java - How can a singly-linked list have two heads, and what does it mean to find their "common node"? -
the javadocs methods below includes:
the singly linked list in problem has 2 heads,
n1
,n2
, merge @ common node. return first common node accessible bothn1
,n2
. must run in o(n) time.
i don't understand purpose of code. how can singly-linked list have 2 heads? common list (or common node), , why returned?
could provide examples of input list or lists, , or after findcommonlist
method returns?
the code is:
public static<e> listnode<e> findcommonlist(listnode<e> n1, listnode<e> n2) { int length1 = getlength(n1); int length2 = getlength(n2); if (length1 > length2) n1 = advance(n1, length1 - length2); else n2 = advance(n2, length2 - length1); while (n1 != n2) { n1 = n1.next; n2 = n2.next; } return n1; } private static<e> listnode<e> advance(listnode<e> n, int k) { while (k > 0) { n = n.next; k--; } return n; } private static<e> int getlength(listnode<e> n) { int total = 0; while (n != null) { total++; n = n.next; } return total; }
i can't see code listnode
, i'm guessing it's pretty typical single-linked list, reference data of type e
, reference next listnode
, called next
. last listnode
point next
null
. ignoring references data, typical list this:
lna→lnb→lnc→…→lnz→null
one of (many) problems kind of structure no 1 list "owns" of these listnode
instances, multiple lists can tangled up:
ln0→ln1→ln2↘ lnq→lnr→…→lnz→null lna→lnb→lnc↗
the findcommonlist
method takes 2 listnode
references, n1
, n2
, , goes searching first node "to right" have in common, marks start of common tail.
what n1
, n2
share common tail depends on start. putting them in obvious places:
n1 ↓ ln0→ln1→ln2↘ lnq→lnr→…→lnz→null lna→lnb→lnc↗ ↑ n2
...would return lnq
start of common tail. (if n2
had instead started @ lnz
, result couldn't have included lnq
--- it's no longer in 1 of lists, , not common them both.)
the javadoc implies code works in situation 1 above, handles few related cases may @ first appear different, when n1
, n2
point different elements of same list:
n1 ↓ ln0→ln1→ln2→ln3→ln4→…→null ↑ n2
or when point 2 unrelated lists... since lists end reference null
, 2 "completely independent" lists return null
start of (zero-length) common tail:
n1 ↓ ln0→ln1→ln2→ln3→ln4↘ null lna→lnb→lnc↗ ↑ n2
how findcommonlist
works
the first thing findcommonlist
find how "far" n1
, n2
end of respective lists (how many elements separate each null
).
in example, n1
"2 farther" n2
:
n1 ↓ ln0→ln1→ln2→ln3→ln4↘ lnq→…→lnz→null lna→lnb→lnc↗ ↑ n2
then, advances farther of 2 references same distance null
other. elements skipped on can't conceivably part of common tail, because there's no way common tail can longer 1 of input lists.
after advancing n1
:
n1 ↓ ln0→ln1→ln2→ln3→ln4↘ lnq→…→lnz→null lna→lnb→lnc↗ ↑ n2
now we've reached while
loop, can reworded as:
start: if n1 , n2 point same listnode: return listnode otherwise: advance n1 , n2 each 1 hop right go "start"
this bit said above "goes searching first node 'to right' have in common". when it's done, n1
, n2
both point @ same listnode
, lnq
, returned:
n1 ↓ ln0→ln1→ln2→ln3→ln4↘ lnq→…→lnz→null lna→lnb→lnc↗ ↑ n2
note works in other cases outlined above, too.
if n1
, n2
refer 2 independent lists:
n1 ↓ ln0→ln1→ln2→ln3→ln4↘ null lna→lnb→lnc↗ ↑ n2
first, farther reference advance:
n1 ↓ ln0→ln1→ln2→ln3→ln4↘ null lna→lnb→lnc↗ ↑ n2
and while
loop advance both references in lockstep until reach "node" 2 lists have in common, null
:
n1 ↓ ln0→ln1→ln2→ln3→ln4↘ null lna→lnb→lnc↗ ↑ n2
if n1
, n2
point same list, it's easier:
n1 ↓ ln0→ln1→ln2→ln3→ln4→…→null ↑ n2
findcommonlist
start advancing far reference, same before:
n1 ↓ ln0→ln1→ln2→ln3→ln4→…→null ↑ n2
...and it's done! findcommonlist
return reference ln3
, without ever executing body of while
loop.
finally, if n1
, n2
start pointing same listnode
:
n1 ↓ ln0→ln1→ln2→ln3→ln4→…→null ↑ n2
...the adjustment step nothing ("advance 0 hops"), , ln0
returned, again without executing body of while
loop.
Comments
Post a Comment