the load-balancing approximation
You have a pile of jobs with known durations and m identical machines, and you must assign every job to some machine. Each machine runs its assigned jobs one after another; the time the LAST machine finishes is called the makespan, and you want to make that finishing time as small as possible — finish the whole batch fast. Deciding the optimal assignment is NP-hard, but a dead-simple greedy rule gets you within a factor of 2, and a small tweak gets you to 4/3.
The greedy rule (list scheduling) is: take the jobs one at a time and assign each to whichever machine is currently least loaded. Why does this never exceed twice the optimum? Look at the machine that finishes last, and at the LAST job j it was given. At the moment j was placed, that machine was the least loaded, so its load-before-j was at most the average load over all machines, which is (total work) / m. Two clean lower bounds on OPT pin everything down: the optimal makespan is at least the average load (total / m), since some machine must do at least its share; and it is at least the largest single job (that job has to run somewhere). The finishing machine's time is its load-before-j plus job j, which is at most average + (largest job) <= OPT + OPT = 2 * OPT. So plain greedy is a 2-approximation. If you first SORT jobs from longest to shortest before placing them (longest-processing-time first), the same style of argument tightens the guarantee to 4/3 * OPT, because by the time small jobs arrive the machines are already well balanced.
This is one of the most practical approximation results, the backbone of how schedulers and load balancers actually split work across servers or cores. The honest points: the two lower bounds (average load and max job) are again the surrogate-for-OPT trick, computable stand-ins for the value you cannot find directly. Plain greedy works online — it can place each job as it arrives, with no knowledge of the future — which is why it is so widely deployed; sorting first needs all jobs up front but buys the better 4/3 ratio. As always these are worst-case ceilings; on typical workloads greedy lands much closer to optimal.
Jobs of length 3,3,2,2,2 onto m=2 machines, greedy in this order: M1<-3, M2<-3, M1<-2 (M1=5), M2<-2 (M2=5), M1<-2 (M1=7). Makespan 7. Sorting longest-first gives 3,3,2,2,2 (same here) but better balancing in general; optimum is 6 (split as {3,3} and {2,2,2}), and 7 <= 2*6 comfortably.
Assign each job to the least-loaded machine; bounded by average load and largest job, hence 2 * OPT.
Plain greedy is a 2-approximation and works online (job by job); sorting longest-first improves it to 4/3 but needs all jobs in advance. Neither beats the two lower bounds — average load and the single largest job — which together force any schedule's makespan.