Go语言每日一练——链表篇(五)

传送门

牛客面试笔试必刷101题 ----------------合并k个已排序的链表

题目以及解析

题目

Go语言每日一练——链表篇(五)_第1张图片

解题代码及解析

解析

这一道题与昨天的合并链表题目类似,但是由于有K个且时间复杂度要求控制在O(nlogn),这里主要有两种解法:一种是依旧使用归并来合并,一种则是利用堆这种数据结构来实现。

代码

方法一:堆(优先队列)

package main
import _"fmt"
import . "nc_tools"
import "container/heap"

/*
 * type ListNode struct{
 *   Val int
 *   Next *ListNode
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param lists ListNode类一维数组 
 * @return ListNode类
*/
func mergeKLists( lists []*ListNode ) *ListNode {
    p:=hp{}
    for _,head:=range lists{
        if head!=nil{
           p=append(p,head)
        }
    }
    heap.Init(&p)//初始化堆
    curr:=&ListNode{}
    dump:=curr
    for len(p)>0{
        node:=heap.Pop(&p).(*ListNode)
        if node.Next!=nil{
           heap.Push(&p,node.Next)
        }
        curr.Next=node
        curr=curr.Next
    }
    return dump.Next
}

//定义小根堆
type hp []*ListNode

func (p hp) Len() int{
    return len(p)
}
func (p hp)Less(i,j int) bool{  //通过该函数来确定小根堆还是大根堆
    return p[i].Val<p[j].Val
}

func (p hp)Swap(i,j int){
    p[i],p[j]=p[j],p[i]
}

func (p *hp)Push(value interface{}){
    *p=append(*p,value.(*ListNode))
}

func (p *hp)Pop() any{
    a:=*p
    value:=a[len(a)-1]
    *p=a[:len(a)-1]
    return value
}

方法二:分治

package main

import (
	_ "container/list"
	_ "fmt"
	. "nc_tools"
	_ "net"
)

/*
 * type ListNode struct{
 *   Val int
 *   Next *ListNode
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param lists ListNode类一维数组
 * @return ListNode类
 */
func Merge(list1 *ListNode, list2 *ListNode) *ListNode {
	dump := &ListNode{}
	current := dump
	for list1 != nil && list2 != nil {
		if list1.Val < list2.Val {
			current.Next = list1
			list1 = list1.Next
		} else {
			current.Next = list2
			list2 = list2.Next
		}
        current=current.Next
	}
	if list1 != nil {
		current.Next = list1
		list1 = list1.Next
	}
	if list2 != nil {
		current.Next = list2
		list2 = list2.Next
	}
	current = current.Next
	return dump.Next
}

func mergeKLists(lists []*ListNode) *ListNode {
	m := len(lists)
	if m == 0 {
		return nil
	}
	if m == 1 {
		return lists[0]
	}
	left := mergeKLists(lists[:m/2])
	right := mergeKLists(lists[m/2:])
	return Merge(left, right)
}

总结:

这题依旧是一道合并链表题,但是简单的遍历来挨个合并会使时间复杂度上升到O(n^2),所以需要采取一些巧劲来实现,但是玩具的最好的还是使用堆来解题,可以更好了解到堆泛型在Go语言中如何去使用。

你可能感兴趣的:(Go语言每日一题,golang,链表,开发语言,数据结构,算法)