Let\'s say you\'ve got an airplane, and it is low on fuel. Unless the plane drops 3000 pounds of passenger weight, it will not be able to reach the next airport. To save t
@James has the answer in the comments: a std::priority_queue if you can use any container, or a combination of std::make_heap and std::pop_heap (and std::push_heap) if you want to use something like a std::vector
.
@Blastfurnace was on the right track. You use quickselect where the pivots are weight thresholds. Each partition splits one set of people into sets, and returns the total weight for each set of people. You continue breaking the appropriate bucket until your buckets corresponding to the highest weight people are over 3000 pounds, and your lowest bucket that is in that set has 1 person (that is, it can't be split any further.)
This algorithm is linear time amortized, but quadratic worst case. I think it is the only linear time algorithm.
Here's a Python solution that illustrates this algorithm:
#!/usr/bin/env python
import math
import numpy as np
import random
OVERWEIGHT = 3000.0
in_trouble = [math.floor(x * 10) / 10
for x in np.random.standard_gamma(16.0, 100) * 8.0]
dead = []
spared = []
dead_weight = 0.0
while in_trouble:
m = np.median(list(set(random.sample(in_trouble, min(len(in_trouble), 5)))))
print("Partitioning with pivot:", m)
lighter_partition = []
heavier_partition = []
heavier_partition_weight = 0.0
in_trouble_is_indivisible = True
for p in in_trouble:
if p < m:
lighter_partition.append(p)
else:
heavier_partition.append(p)
heavier_partition_weight += p
if p != m:
in_trouble_is_indivisible = False
if heavier_partition_weight + dead_weight >= OVERWEIGHT and not in_trouble_is_indivisible:
spared += lighter_partition
in_trouble = heavier_partition
else:
dead += heavier_partition
dead_weight += heavier_partition_weight
in_trouble = lighter_partition
print("weight of dead people: {}; spared people: {}".format(
dead_weight, sum(spared)))
print("Dead: ", dead)
print("Spared: ", spared)
Output:
Partitioning with pivot: 121.2
Partitioning with pivot: 158.9
Partitioning with pivot: 168.8
Partitioning with pivot: 161.5
Partitioning with pivot: 159.7
Partitioning with pivot: 158.9
weight of dead people: 3051.7; spared people: 9551.7
Dead: [179.1, 182.5, 179.2, 171.6, 169.9, 179.9, 168.8, 172.2, 169.9, 179.6, 164.4, 164.8, 161.5, 163.1, 165.7, 160.9, 159.7, 158.9]
Spared: [82.2, 91.9, 94.7, 116.5, 108.2, 78.9, 83.1, 114.6, 87.7, 103.0, 106.0, 102.3, 104.9, 117.0, 96.7, 109.2, 98.0, 108.4, 99.0, 96.8, 90.7, 79.4, 101.7, 119.3, 87.2, 114.7, 90.0, 84.7, 83.5, 84.7, 111.0, 118.1, 112.1, 92.5, 100.9, 114.1, 114.7, 114.1, 113.7, 99.4, 79.3, 100.1, 82.6, 108.9, 103.5, 89.5, 121.8, 156.1, 121.4, 130.3, 157.4, 138.9, 143.0, 145.1, 125.1, 138.5, 143.8, 146.8, 140.1, 136.9, 123.1, 140.2, 153.6, 138.6, 146.5, 143.6, 130.8, 155.7, 128.9, 143.8, 124.0, 134.0, 145.0, 136.0, 121.2, 133.4, 144.0, 126.3, 127.0, 148.3, 144.9, 128.1]
I would probably use std::nth_element
to partition off the 20 heaviest people in linear time. Then use a more complex method to find and bump off the heaviest of the heavies.
Assuming that, like people's weights, you have a good idea of what the maximum and minimum values are likely to be use a radix sort to sort them in O(n). Then simply work from the heaviest end of the list towards the lightest. Total running time: O(n). Unfortunately, there isn't an implementation of a radix sort in the STL, but it's pretty straightforward to write.
You could make one pass over the list to get the mean and the standard deviation, then use that to approximate the number of people that have to go. Use partial_sort to generate the list based on that number. If the guess was low, use partial_sort again on the remainder with a new guess.
This won't help for your proxy problem, however:
For 1,000,000 passengers to drop 3000 pounds of weight, each passenger must lose (3000/1000000) = 0.003 lbs per person. That could be achieved through jettisoning every ones shirt, or shoes, or probably even fingernail clippings, saving everyone. This assumes efficient collection and jettison before the weight loss needed increased as the plane used more fuel.
Actually, they don't allow fingernail clippers on board anymore, so that's out.