Refuse a copied random list that loops back
A deep copy whose last node links back to the first copy passed Outline Snapshot Duplicator (copy-list-with-random-pointer) in C++, Java, JavaScript and Python, and failed in C with no reason given.
Root cause: checkAnswer compares only the serialized value, so the serializer is the only code that sees the returned structure. The random-list serializers (randomListToJson, randomListJson, randomListToArray, _random_list_to_array) kept a seen set for termination but treated a revisit as the end of the list, so a ring was cut at its first repeated node and printed exactly as a correct copy. #405 fixed this for the ListNode serializers; the random list uses the separate Node type and its own serializers, which kept the old loop from the initial import. A judge case cannot catch it, because an expected value in JSON cannot describe a cycle.
C differed because json_random_list had no seen set, only a 10000-node buffer cap: on the ring it printed 10000 entries per non-empty case with random indices pointing at late repeats, and no error field, so the candidate saw a wrong answer without a reason.
This change reports a revisit as an error in all five serializers with the message #405 already uses, "Returned list must not reach a node twice.", and keeps the seen set so serialization still terminates. C gets the same Floyd check as json_list, run after the deep-copy walk, which is capped at 10000 nodes, so a ring of copies is walked to that cap before the check refuses it. Correct copies and the empty case are unaffected.
The regression test compiles and runs the cyclic copy against the judge in C, C++ and Java and expects that message on every non-empty case; it fails on main and passes with this change. JavaScript and Python get the same source check #405 added for the plain list serializers.
The C serializer also printed its two existing refusals where the answer goes: a shallow copy's "Returned list must be a deep copy." became the actual value, and a stray random pointer's "Returned random pointer must stay inside the copied list." landed inside the array, so both failed with no reason. It now checks every random pointer before the opening [ and reports both through null,"error":, as the cycle check does, which lines C up with C++ and Java; the JavaScript and Python half of #364 stays with #372. json_graph has the same pattern and is left for a separate change.
Closes #417
Summary by cubic
Fixes the random-list serializers so a deep copy whose last node links back to the first is rejected instead of being accepted as a correct acyclic list.
- The serializers in C, C++, Java, JavaScript, and Python now report
Returned list must not reach a node twice.on a revisit, matching the existing plain-list behavior. - C also gets the same Floyd cycle check as the plain-list serializer, run before the buffer fills.
- C now reports a shallow copy and a stray random pointer through the error field instead of embedding them in the answer; a shallow copy that also loops is refused as a shallow copy.
- Regression tests compile and run a cyclic copy and the C error cases in C, C++, and Java and assert the error messages; JavaScript and Python get source-level checks. The compiled harness tests now share one compile-and-run helper.