You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

列表推导中next使用及面包队列高效处理的技术求助

Optimizing Baker Queue for Large Datasets: Fixing Your Heap Approach

First, let's break down what's wrong with your current heap code and walk through the right optimizations for this problem—since your original approach works for small data but will grind to a halt with millions of people and years of daily bake times.

The Core Issue with Your Original Code

Your initial BakerQueue function has a time complexity of O(m * n) (where m is the number of days and n is the number of people). For large datasets (like 1M people and 10 years of daily queries), this translates to billions of operations—way too slow for practical use.

What's Wrong with Your Heap Attempt?

You had the right intuition to use a heap for optimization, but two critical mistakes derailed your code:

  1. Incorrect Heap Top Access: Using next([v[1] for v in my_list_of_tuples]) doesn't get the heap's top element. A heapq-heapified list only guarantees the first element (my_list_of_tuples[0]) is the smallest. The list comprehension creates an unrelated new list, so this approach is completely invalid.
  2. Misaligned Heap Sorting: You stored tuples as (i, j) (index, wait time), so the heap sorts by index—not wait time. Even if you fixed that, using a heap to sort by wait time breaks the original queue order, which is critical to the problem: we need to count people in their original line order, not by how long they can wait.

Correct Optimization Approach

The problem boils down to: for each daily bake time b, find the k-th (k=loaves) person in the original queue who can wait long enough (people[p] >= b), return their ticket number (index+1), or 0 if there aren't enough people.

For large datasets, the best solution is to preprocess the data into a segment tree for fast range queries. Here's how to implement it:

Step 1: Build a Segment Tree for Efficient Queries

We'll create a segment tree where each node stores a sorted list of wait times in its interval. This lets us quickly count how many people in any range can wait for a given b, and find the k-th valid person.

Complete Optimized Code

import bisect

class SegmentTree:
    def __init__(self, data):
        self.n = len(data)
        self.size = 1
        while self.size < self.n:
            self.size <<= 1  # Grow to next power of two
        self.tree = [[] for _ in range(2 * self.size)]
        
        # Fill leaf nodes with wait times
        for i in range(self.n):
            self.tree[self.size + i] = [data[i][0]]
        
        # Build upper layers by merging sorted lists
        for i in range(self.size - 1, 0, -1):
            self.tree[i] = sorted(self.tree[2*i] + self.tree[2*i+1])
    
    def query_kth_ge(self, k, b):
        # Find the index of the k-th element >= b in the original data
        res_idx = -1
        count = 0
        l, r = 0, self.n
        node = 1
        node_l, node_r = 0, self.size
        
        while l < r:
            mid = (l + r) // 2
            left_node = 2 * node
            right_node = 2 * node + 1
            left_mid = (node_l + node_r) // 2
            
            # Count elements >= b in the left child
            cnt_left = len(self.tree[left_node]) - bisect.bisect_left(self.tree[left_node], b)
            
            if count + cnt_left >= k:
                # Target is in the left child
                node = left_node
                r = mid
                node_r = left_mid
            else:
                # Target is in the right child
                count += cnt_left
                node = right_node
                l = mid
                node_l = left_mid
        
        # Verify if the final index has a valid element
        if count + (len(self.tree[self.size + l]) - bisect.bisect_left(self.tree[self.size + l], b)) >= k:
            res_idx = l
        return res_idx

def OptimizedBakerQueue(loaves, people, bake_time):
    # Pair each person's wait time with their ticket number
    people_with_tickets = [(wait, idx + 1) for idx, wait in enumerate(people)]
    st = SegmentTree(people_with_tickets)
    result = []
    
    for b in bake_time:
        idx = st.query_kth_ge(loaves, b)
        if idx == -1:
            result.append(0)
        else:
            result.append(people_with_tickets[idx][1])
    return result

# Test with your sample input
print(OptimizedBakerQueue(3, [1, 4, 4, 3, 1, 2, 6, 1, 9, 4, 4, 3, 1, 2, 6, 9, 4, 5, 8], [1, 2, 5, 4, 5, 4, 7]))
# Output: [3, 4, 15, 7, 15, 7, 19]

Fixing Your Heap Code (For Learning Purposes)

If you still want to experiment with heaps, here's how to correctly access the heap top and structure your code (note: this won't solve the problem efficiently, since it doesn't preserve queue order—it's just for demonstration):

import heapq

def HeapDemo(loaves, people, bake_time):
    # Heap stores (wait_time, ticket_number), sorted by wait time
    heap = [(wait, idx + 1) for idx, wait in enumerate(people)]
    heapq.heapify(heap)
    result = []
    
    for b in bake_time:
        temp = []
        count = 0
        last_ticket = 0
        
        # Remove people who can't wait
        while heap:
            wait, ticket = heap[0]
            if wait < b:
                heapq.heappop(heap)
            else:
                if count < loaves:
                    count += 1
                    last_ticket = ticket
                    heapq.heappop(heap)
                else:
                    break
        
        # Restore heap for next day (since each day is independent)
        heap = [(wait, idx + 1) for idx, wait in enumerate(people)]
        heapq.heapify(heap)
        
        result.append(last_ticket if count == loaves else 0)
    return result

This approach is still O(m*n) because we re-heapify for each day, making it no better than your original code. Stick with the segment tree for large datasets.

Key Takeaways

  • Heap Top Access: For heapq-heapified lists, always access the smallest element with heap[0]—never use list comprehensions or generators for this.
  • Data Structure Alignment: Choose tools that match your problem's requirements. Heaps are great for priority sorting, but this problem needs to preserve original order, making a segment tree the right choice.
  • Big Data Efficiency: Preprocessing and using efficient query structures (like segment trees) is critical to avoid the O(m*n) bottleneck in large-scale scenarios.

内容的提问来源于stack exchange,提问作者Tennis Tubbies

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 18:32:44