##Preface This review treats the code as a professional exercise rather than an academic one.
##Introduction
Your intuition about one pass versus two passes was spot on.
Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. -- Donald Knuth
You Ain't Gonna Need It
In most cases O(n log n) time complexity is highly likely to be good enough. Sorting the array first makes the logic simple.
Pseudo-Code
MyArray = Input.sort
End = MyArray.length - 1
Candidate0 = 0
Candidate1 = MyArray[End] * MyArray[0] * MyArray[1]
Candidate2 = MyArray[End] * MyArray[End - 1] * MyArray[End - 2]
Return Max(Candidate0, Candidate1, Candidate2)
Performance Concerns?
Use a profiler. It is highly unlikely that the critical performance bottleneck of an interesting piece of software is a routine running in O(n log n) time.
Take Advantage of the Platform
Making assumptions about the execution path of a Java program as if it is assembly or C is an error. The Java JIT does branch prediction with one eye on the branch predition, prefetch and cache strategies of the hardware CPU. Java's sort is tuned to the eyeballs. Many man hours have gone into optimizing it to work with the JVM's underlying optimization strategies.
Hand rolled code that branches randomly is likely to see less optimization and memory latency of cache misses could swamp the theoretical efficiency of O(n) versus O(n log n) even in a critical section. Use a profiler.
##Conclusion Your intuition was sound. Correctness and clarity should come first. Performance should come later, if at all, and then only when it actually matters. The intuition just wasn't pushed far enough.
Epilogue
If, as some programmers believe, bugs are proportional to lines of code and software maintenance is a substantial fraction of total software costsoftware maintenance is a substantial fraction of total software cost, then it stands to reason that more compact code will contain fewer bugs and cost less.
Often it is easier to read as well:
public int max_prod_three(int[] A){
private int end = A.length;
private int[] MySortedArray = A.sort();
return Math.max(MySortedArray[0] * MySortedArray[1] * MySortedArray[end],
MySortedArray[end - 2] * MySortedArray[end - 1] * MySortedArray[end],
0);
}
###Afterward
Programs must be written for people to read, and only incidentally for machines to execute. -- Ableson and Sussman