SoftwareSideHustles
Skills

What Makes One Coding Solution Better Than Another?

Correctness first, then fitness for the constraints, then clarity. A practical framework for comparing two implementations, with examples where the honest answer is "it depends".

By Software Side Hustles Editorial Team · Published · Updated · 3 min read

"Which code is better?" sounds like a matter of taste. In evaluation work it shouldn't be. A good comparison follows a consistent order of priorities and ties every judgement to the stated constraints.

The priority order

  1. Correctness — does it produce the right result for every input the constraints allow?
  2. Fitness for the constraints — are its time, memory and other costs acceptable for the stated sizes and environment?
  3. Robustness — does it handle failure modes sensibly (invalid input, empty input, very deep or large data)?
  4. Clarity and maintainability — would a teammate understand and change it safely?
  5. Style — idioms and conventions, which matter least.

Most bad comparisons skip step 1 or jump straight to step 5.

Correctness beats speed

Consider "return the largest sum of any non-empty contiguous subarray", where values may be negative. A quadratic brute force is correct. A linear version of Kadane's algorithm initialised with best = 0 is faster — and wrong: for [-3, -1, -2] it returns 0 instead of -1, because it can never report a negative total.

The faster solution loses, however elegant it looks. (It becomes the better solution the moment best is initialised to the first element.) You can work through this exact case in our free lab.

"Better" depends on the constraints

Two correct solutions to "does this array contain a duplicate?":

javascript
// A: nested loops — O(n²) time, O(1) extra memory
for (let i = 0; i < nums.length; i++)
for (let j = i + 1; j < nums.length; j++)
if (nums[i] === nums[j]) return true;
// B: hash set — O(n) expected time, O(n) extra memory
const seen = new Set();
for (const n of nums) { if (seen.has(n)) return true; seen.add(n); }

With up to 100,000 elements and plenty of memory, B wins clearly: A could need about 5 billion comparisons. With ten elements on a severely memory-constrained device, A is perfectly reasonable. Always state which constraint decided it.

Big-O is a starting point, not the verdict

  • Constants matter at small sizes. A simple O(n²) loop over 20 items can beat a cleverer algorithm with heavy setup.
  • Typical and worst case differ. Hash-set operations are expected O(1); worst-case behaviour depends on the implementation.
  • Memory is a cost too. An O(n) extra-memory solution may be unacceptable for streaming data that doesn't fit in memory.

When the honest answer is "it depends"

Sometimes the brief leaves out the fact that decides the comparison. Computing the depth of a binary tree is a good example:

  • a recursive version is short and mirrors the definition, but in CPython with the default recursion limit (1,000) a degenerate tree of 5,000 nodes raises RecursionError;
  • an iterative version with a queue handles any depth but is longer.

If the brief doesn't say how deep trees can be, the strongest answer is "it depends on the maximum depth" — followed by what you would need to know and what you'd choose by default. "It depends" with no explanation is not an answer; "it depends on X, and if X is unknown I'd choose B because…" is.

The reverse also applies: if the constraints do settle the question, saying "it depends" is a hedge, not insight.

Readability is a real criterion

Between two correct, adequately fast solutions, prefer the one that:

  • states its intent directly (a Set named seen reads as "have I seen this?");
  • uses standard library tools instead of hand-rolled ones (bisect, statistics.median, collections.Counter);
  • has fewer places to make an off-by-one error.

For example, both of these check whether two strings are anagrams:

python
sorted(a) == sorted(b) # O(n log n), very readable
Counter(a) == Counter(b) # O(n), also readable

For short strings either is fine, and saying so is better than inventing a performance problem.

A template for your justification

Prefer B. Both are correct on all listed tests, including the empty case. The constraints allow up to 10⁵ elements with ample memory; A is O(n²) (≈5×10⁹ comparisons worst case) while B is O(n) expected time with O(n) extra memory, which the brief permits. B is also clearer. A would be preferable only under tight memory limits, which don't apply here.

It names the decision, the evidence, the deciding constraint and the condition under which the answer would change.

Practise

Our free Code Comparison lab includes all three situations above: a clear trade-off, a fast-but-wrong solution and a genuine "it depends".

Cookies on this site

We use essential cookies to run the questionnaire, practice labs and sign-in. With your permission we'd also like to use analytics to understand which pages help people. Rejecting never limits any feature. Cookie policy