Solve problems by sorting with custom orders and making locally optimal choices that lead to a global optimum
Sort data to expose structure, then take greedy steps based on problem-specific criteria (comparators, endpoints, frequencies).
Use when ordering unlocks a simple greedy rule (intervals, scheduling, top-k, custom orderings) or when range/keys are small (counting/bucket).
Define ordering logic to drive greedy selection or grouping
from functools import cmp_to_key
def custom_sort_pairs(pairs):
# Example: sort by first asc, then second desc (custom comparator)
def cmp(a, b):
if a[0] != b[0]:
return -1 if a[0] < b[0] else 1
# tie-break on second descending
if a[1] != b[1]:
return -1 if a[1] > b[1] else 1
return 0
pairs.sort(key=cmp_to_key(cmp))
return pairs
def largest_number(nums):
# Classic comparator usage example
arr = list(map(str, nums))
def cmp(a, b):
if a + b > b + a: return -1
if a + b < b + a: return 1
return 0
arr.sort(key=cmp_to_key(cmp))
res = ''.join(arr).lstrip('0')
return res or '0'
Sort by start and combine overlapping intervals
def merge_intervals(intervals):
intervals.sort(key=lambda x: x[0])
merged = []
for s, e in intervals:
if not merged or s > merged[-1][1]:
merged.append([s, e])
else:
merged[-1][1] = max(merged[-1][1], e)
return merged
Exploit bounded key range for linear-time grouping and ordering
def counting_sort(arr, max_val=None):
if not arr:
return []
if max_val is None:
max_val = max(arr)
count = [0] * (max_val + 1)
for x in arr:
count[x] += 1
i = 0
for v, c in enumerate(count):
for _ in range(c):
arr[i] = v
i += 1
return arr
def template(*args, **kwargs):
# General template placeholder
pass
Sorting dominates unless using counting/bucket with small key range.
In-place sort often O(1); counting/bucket needs O(k) buckets.