Wenxin Yiyan VS Xunfei Xinghuo VS chatgpt (70) -- Introduction to Algorithms 6.5 9 questions

9. Please design an algorithm with a time complexity of (n lgk), which can merge k ordered linked lists into an ordered linked list, where n is the total number of elements contained in all input linked lists. (Hint: Use a min-heap for k-way merges.

In a word:

To design an algorithm with a time complexity of O(n log k) to merge k ordered linked lists into an ordered linked list, you can use the minimum heap to implement k-way merge.

Here are the steps of an algorithm:

1. Insert the elements in each linked list into the min heap, so that the elements in each linked list will be sorted according to their values.

2. Create an empty linked list to store the merged results.

3. Repeat the following steps until the minimum heap is empty:

a. Take the smallest element from the min heap and insert it at the end of the empty linked list.

b. If the element from a linked list has not been processed, insert the next element in the linked list into the minimum heap.

c. If the element from all linked lists has been processed, all linked lists have been merged, and the empty linked list can be returned directly.
4. Return an empty linked list, which is the merged result.

The time complexity of the algorithm is O(n log k), where n is the total number of elements contained in all input linked lists, and log k is the time complexity of inserting and deleting operations on the min-heap.

insert image description here

Xunfei Spark:

In order to merge k sorted linked lists into one sorted linked list, we can use min-heap to complete k-way merge. First, we need to create an array of size n to store the current element of each linked list. Then, we iterate through all linked lists, adding their elements to the array. Next, we use a min-heap to find the smallest element in the array and add it to the resulting linked list. Finally, we remove the smallest element from the min heap and remove it from the original linked list. Repeat this process until all linked lists have been processed.

Following are the steps of the algorithm:

1. Initialize an array of size n arrto store the current element of each linked list.

2. Traverse all linked lists and add their elements to the array arr.

3. Create a min-heap of size n minHeap.

4. arrPop the smallest element from the array and add it to the result list result.

5. Delete the smallest element from the original linked list.

6. If the minimum heap is not empty, take the next node of the root node of the minimum heap as the new minimum element and add it to the array arr.

7. If the size of the minimum heap is less than or equal to 1, jump out of the loop.

8. Return the result linked list result.

Here is the Python implementation of the algorithm:

import heapq

def mergeKSortedLists(lists):
    n = sum([len(lst) for lst in lists])
    arr = [0] * n
    pos = 0

    # 将所有链表的元素添加到数组 arr 中
    for lst in lists:
        for val in lst:
            arr[pos] = val
            pos += 1

    # 使用最小堆来合并数组 arr
    minHeap = []
    for i in range(n):
        heapq.heappush(minHeap, (arr[i], i))

    result = []
    prev_val = None
    prev_idx = None

    while minHeap and len(result) < n:
        curr_val, curr_idx = heapq.heappop(minHeap)
        if curr_val != prev_val or (curr_idx is not None and curr_idx != prev_idx):
            result.append(curr_val)
            prev_val = curr_val
            prev_idx = curr_idx if curr_idx is not None else n + 1
        elif len(result) < n:
            result.append(curr_val)
            prev_val = curr_val
            prev_idx = n + 1

        if minHeap:
            next_val, _ = heapq.heappop(minHeap)
            arr[curr_idx] = next_val
            if next_val != arr[curr_idx]:
                heapq.heappush(minHeap, (arr[curr_idx], curr_idx))
                arr[next_val] = arr[curr_idx]
                heapq.heappush(minHeap, (arr[next_val], next_val))

insert image description here

insert image description here

360 Smart Brain:

1. First, create a minimum heap.

2. For each input linked list, take out its first k elements in turn, and insert them into the minimum heap.

3. Then pop k elements from the minimum heap sequentially until the minimum value of the popped k elements is greater than or equal to the value of the last element in the current input list. Insert the popped element into the input list.

4. Repeat step 3 until the minimum heap is empty or the popped element is less than or equal to the value of the last element in the input list. Finally, the remaining elements are added to the input linked list.

5. Finally, pop the k elements in the minimum heap in order and insert them into the end of the input linked list.

The time complexity is O(n lgk), where n is the total number of elements contained in all input linked lists, and k is the number of input linked lists. Since the insert and pop operations of the minimum heap are constant time complexity, the total time complexity is O(n lgk).

insert image description here

chatglm:

Here is an algorithm with time complexity (n lgk) for merging k sorted lists into one sorted list:

1. Create a minimum heap for storing the head nodes of k ordered linked lists.

2. Add the head node of each ordered linked list to the minimum heap.

3. Each time a node is taken from the minimum heap, and all elements of its linked list are added to the result linked list.

4. If there are remaining elements in the current linked list, add its head node to the min heap.

5. Repeat steps 3 and 4 until all linked list elements are added to the resulting linked list.

The time complexity of the algorithm is mainly composed of the operation of the minimum heap and the traversal of the linked list. In the worst case, each linked list needs to be traversed once, so the time complexity of traversing a linked list is O(n). The operation time complexity of the minimum heap is O(lgk), so the time complexity of the entire algorithm is O(n lgk).

The following is the implementation code of the algorithm:

def mergeKSortedLists(lists):  
   n = len(lists)  
   total_elements = sum(len(list_) for list_ in lists)  
   min_heap = []
   # Add the head of each sorted list to the min heap  
   for i in range(n):  
       min_heap.append(lists[i][0])
   # Merge the lists by 反复地将最小堆顶元素添加到结果列表中  
   result = []  
   while min_heap:  
       min_value = heapq.heappop(min_heap)  
       result.append(min_value)
       # If the current list still has elements, add its head to the min heap  
       if lists[i][1]!= None:  
           min_heap.append(lists[i][1])
   return result  

Among them, lists is a list containing k ordered linked lists, each linked list is a tuple, including the head node and remaining elements of the linked list. In the function, we first calculated the total number of elements in all linked lists, then created a min-heap, and added the head node of each linked list to the min-heap. Next, we use the heapq module to iteratively add the top element of the min-heap to the result list, and add the head node of the current linked list to the min-heap until all elements of the linked list are added to the result list. Finally, we return the result list.

insert image description here

insert image description here

Tongyi Qianqian:

First, we put all input linked lists into a min-heap. For each linked list, we take its last element and add it to the new linked list. We then decrement the size of the heap by one and remove the heap from the linked list if the size of the heap is zero. We repeat this process until all linked lists are merged.

Here is the Python implementation of the algorithm:

from collections import MinHeap

def merge_k_sorted_lists(lists):
    heap = MinHeap()
    for list in lists:
        heapq.heappush(heap, list[-1])
    merged_list = []
    while heap:
        merged_list.append(heap.heappop())
    return merged_list

The time complexity of this algorithm is (n lgk), because in the worst case, we need to traverse all input linked lists and perform an insertion operation on each linked list. Since we use a min-heap, the time complexity of the insert operation is logk. The total time complexity is n logk.

insert image description here

Tiangong:

Ok, based on hints, we can use min-heap to do k-way merge. Specific steps are as follows:

1. First, we need to define a structure ListNode, which represents a node of the linked list.

struct ListNode {
    int val;
    ListNode* next;
    // 指向下一个节点的指针
};

2. Then, we need to define a comparison function cmp, which is used to compare the size of two nodes in order to insert them into the min heap.

bool cmp(ListNode* a, ListNode* b) {
    return a->val > b->val;
}

3. Next, we need to use a minimum heap of size k to store the head nodes of k ordered linked lists. We can use priority_queue in C++, which is a heap structure and uses a small top heap by default.

priority_queue<ListNode*, vector<ListNode*>, greater<ListNode*>> minHeap;

4. Then, we traverse each linked list and insert their head nodes into the min heap.

for (int i = 0; i < k; i++) {
    ListNode* cur = mergedList[i];
    while (cur != NULL) {
        minHeap.push(cur);
        cur = cur->next;
    }
}

5. Finally, we take out the head nodes of each linked list in turn from the minimum heap, and connect them to form an ordered linked list.

ListNode* result = NULL;
while (!minHeap.empty()) {
    ListNode* cur = minHeap.top();
    minHeap.pop();
    if (result == NULL) {
        result = cur;
    } else {
        result->next = cur;
    }
}

6. Finally, we return the head node of the merged ordered linked list.

Time complexity analysis:

1. The time complexity of the insertion operation is O(logk), because the size of the minimum heap is k, and inserting a node only needs to compare it with the top element of the heap and adjust it.

2. The time complexity of the extraction operation is O(1), because the size of the minimum heap is k, and to extract the top element of the heap, it is only necessary to compare and adjust the top element of the heap with the top element of the heap.

3. The total time complexity is O(n logk), where n is the total number of elements contained in all input linked lists. Because it is necessary to traverse each linked list, insert their header nodes into the minimum heap, and take out the header nodes of each linked list from the minimum heap in turn, and connect them to form an ordered linked list.

Hope this answer helps you!

insert image description here

insert image description here

chatgpt:

To design an algorithm with a time complexity of O(n lgk) to merge k ordered linked lists into an ordered linked list, you can use the minimum heap to complete the k-way merge. Here are the steps of the algorithm:

1. Create a minimum heap and initialize it to be empty. This heap will be used to select the current smallest element in the k linked lists.

2. Traverse k ordered linked lists, and insert the head node of each linked list into the minimum heap. At the same time, record the current position pointer of each linked list.

3. Initialize an empty linked list as the merged ordered linked list.

4. When the minimum heap is not empty, perform the following operations:

  • Remove the top element (that is, the current smallest element) from the minimum heap, and add it to the merged sorted linked list.

  • Then, the next node of the linked list where the element is located is inserted into the minimum heap, and the current position pointer of the linked list is updated at the same time.

5. When the minimum heap is empty, the merge process ends. Returns the merged sorted linked list.

Here is an example of implementing the above algorithm using Python code:

import heapq

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def mergeKLists(lists):
    # 创建最小堆,并初始化为空
    min_heap = []
    
    # 将每个链表的头节点插入最小堆中,并记录当前位置指针
    for i in range(len(lists)):
        if lists[i]:
            heapq.heappush(min_heap, (lists[i].val, i))
            lists[i] = lists[i].next
    
    # 初始化合并后的有序链表
    dummy = ListNode(0)
    current = dummy
    
    # 进行 k 路归并
    while min_heap:
        val, i = heapq.heappop(min_heap)  # 移除堆顶元素
        current.next = ListNode(val)      # 将最小元素添加到合并后的链表中
        current = current.next
            
        if lists[i]:
            heapq.heappush(min_heap, (lists[i].val, i))  # 将下一个节点插入最小堆中
            lists[i] = lists[i].next
    
    return dummy.next

The time complexity of this algorithm is O(n lgk), where n is the number of elements contained in all input linked lists and k is the number of sorted linked lists. The overall idea of ​​the algorithm is to use the minimum heap to select the current smallest element and insert it into the merged ordered linked list. At the same time, insert the next node of the linked list where the element is located into the minimum heap, so that the minimum element can be selected in the next round. During the execution of the algorithm, each element is processed once, so the time complexity is O(n). The time complexity of heap insertion and deletion operations is O(lgk). In the worst case, k insertion and deletion operations are required, so the total time complexity is O(n lgk).

insert image description here

insert image description here

Summarize

insert image description here

Guess you like

Origin blog.csdn.net/weixin_48502062/article/details/132082139