Analysis
The current running time is 0(m+n) where m = length(list1)
and n = length(list2)
. Combining the loops reduces the running time to 0(n) where n
is the length of the longer list.
Single Loop Example
Procedure in psuedo code:
calcRange(list1, list2)
length1 = list1.length
length2 = list2.length
stop = maximum(length1, length2)
min1 = list1[0]
max1 = list1[0]
min2 = list2[0]
max2 = list2[0]
loop from i = 1 to stop
if i< length1
min1 = minimum(min1, list1[i])
max1 = maximum(max1, list1[i])
if i< length2
min2 = minimum(min2, list2[i])
max2 = maximum(max2, list2[i])
end loop
return list(min1, max1, min2, max2)
Further refactoring is possible, but not shown to make the high level structure read more clearly.
Semantics
In the review code there is a bit of disconnect between the form of the output and the execution path of the implementation:
The output of the review code is in tuple value form - i.e. the results of both lists are treated as single value and returned simultaneously:
System.out.println("List 1 Range: "+(max - min)+"\tList 2 Range: "+(max2 - min2));
The review code execution path explicitly processes the lists sequentially making List2.range
dependent on finding list1.range
.
Double Loop
Looping over the array lists one at a time creates a compositional type dependency that could be abstracted as list2(list1())
. As way of illustration:
process(list1)
print("List1 range: %d", (list1.max - list1.min))
process(list2)
print("\tList2 range: %d", (list2.max - list2.min))
Is structurally consistent with the 2 loop semantics because with two loops list1
has execution priority.
Single Loop
Using a single loop which partially processes both lists on each iteration directly reflects the tuple semantics of the output. The tuple output implies that the input is also a tuple.
Treating the input as a tuple is Java's default function semantics as well - it is not normal to assume that the first argument to a Java function of airity 2 has execution priority over the second argument. Multiple arguments are parsed to a random access structure, not into a sequential one.
Processing both loops in a single loop has the form of a fixed point calculation that converges toward the ordered pair value (list1.range, list2.range)
with each iteration.
Partial Calculations
The single loop form allows for the possibility of returning the best current value of list1.range
or list2.range
at any time. This facilitates working with streams of arbitrary length and operating closer to real time.
Conclusions
Neither the single loop or double loop approach is objectively better. There are tradeoffs and benefits to each. These can only be evaluated in context. The hazard is that the context for a code snippet on the internet is often assumed to be trivial.