Short answer
Use three rules: sequential blocks add and you keep only the biggest term; nested loops multiply their counts (a loop of n inside a loop of n is n*n = O(n^2)); and a process that halves the remaining work each step is O(log n).
Explanation
A single loop from 0 to n is O(n). So a loop after another loop is still O(n), but a loop inside a loop is O(n^2). Then simplify by dropping constants.
Common mistakes
- Adding nested-loop costs instead of multiplying them.
- Forgetting that library calls inside a loop have their own cost.