前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2021-07-30:两个有序数组间相加和的Topk问题。给定两个有序数组arr1和arr2,再给定一个整数k,返回来自arr1

2021-07-30:两个有序数组间相加和的Topk问题。给定两个有序数组arr1和arr2,再给定一个整数k,返回来自arr1

作者头像
福大大架构师每日一题
发布2021-08-05 16:30:28
7430
发布2021-08-05 16:30:28
举报

2021-07-30:两个有序数组间相加和的Topk问题。给定两个有序数组arr1和arr2,再给定一个整数k,返回来自arr1和arr2的两个数相加和最大的前k个,两个数必须分别来自两个数组。按照降序输出。[要求]时间复杂度为O(klogk)。

福大大 答案2021-07-30:

1.左神方法。大根堆。

时间复杂度:O(klogk)。

空间复杂度:O(k)。

2.我的方法。小根堆。两个有序数组构成一个二维数组。然后从右下往左上遍历,当遍历数量大于等于k时,停止遍历。见图。

时间复杂度:略大于O(k)。

空间复杂度:O(k)。

代码用golang编写。代码如下:

代码语言:javascript
复制
package main

import (
    "fmt"
    "sort"
)

func main() {
    arr1 := []int{1, 2, 3, 4, 5}
    arr2 := []int{3, 5, 7, 9, 11}
    topK := 4
    if true {
        ret := topKSum1(arr1, arr2, topK)
        fmt.Println("左神的方法:", ret)
    }
    if true {
        ret := topKSum2(arr1, arr2, topK)
        fmt.Println("我的方法:", ret)
    }
}

type Node struct {
    index1 int // arr1中的位置
    index2 int // arr2中的位置
    sum    int // arr1[index1] + arr2[index2]的值
}

func NewNode(i1 int, i2 int, s int) *Node {
    ret := &Node{}
    ret.index1 = i1
    ret.index2 = i2
    ret.sum = s
    return ret
}

func topKSum1(arr1 []int, arr2 []int, topK int) []int {
    if len(arr1) == 0 || len(arr2) == 0 || topK < 1 {
        return nil
    }
    N := len(arr1)
    M := len(arr2)
    topK = getMin(topK, N*M)
    res := make([]int, topK)
    resIndex := 0
    maxHeap := make([]*Node, 0)
    set := make(map[int]struct{})
    i1 := N - 1
    i2 := M - 1
    Push(&maxHeap, NewNode(i1, i2, arr1[i1]+arr2[i2]))
    set[x(i1, i2, M)] = struct{}{}
    for resIndex != topK {
        curNode := Pop(&maxHeap)
        res[resIndex] = curNode.sum
        resIndex++
        i1 = curNode.index1
        i2 = curNode.index2
        delete(set, x(i1, i2, M))
        _, ok := set[x(i1-1, i2, M)]
        if i1-1 >= 0 && !ok {
            set[x(i1-1, i2, M)] = struct{}{}
            Push(&maxHeap, NewNode(i1-1, i2, arr1[i1-1]+arr2[i2]))
        }
        _, ok = set[x(i1, i2-1, M)]
        if i2-1 >= 0 && !ok {
            set[x(i1, i2-1, M)] = struct{}{}
            Push(&maxHeap, NewNode(i1, i2-1, arr1[i1]+arr2[i2-1]))
        }
    }
    return res
}

func getMin(a int, b int) int {
    if a < b {
        return a
    } else {
        return b
    }
}

func x(i1 int, i2 int, M int) int {
    return i1*M + i2
}

func Push(maxHeap *[]*Node, node *Node) {
    *maxHeap = append(*maxHeap, node)
}

func Pop(maxHeap *[]*Node) *Node {
    sort.Slice(*maxHeap, func(i, j int) bool {
        return (*maxHeap)[i].sum < (*maxHeap)[j].sum
    })
    ans := (*maxHeap)[len(*maxHeap)-1]
    *maxHeap = (*maxHeap)[0 : len(*maxHeap)-1]
    return ans
}

func topKSum2(arr1 []int, arr2 []int, topK int) []int {
    if len(arr1) == 0 || len(arr2) == 0 || topK < 1 {
        return nil
    }
    N := len(arr1)
    M := len(arr2)
    topK = getMin(topK, N*M)
    maxHeap := make([]int, 0)
    i1Start, i2Start := N-1, M-1
    count := 0
    for {
        for i1, i2 := i1Start, i2Start; i1 >= 0 && i2 < M; i1, i2 = i1-1, i2+1 {
            PushInt(&maxHeap, arr1[i1]+arr2[i2])
            if len(maxHeap) > topK {
                PopInt(&maxHeap)
            }
            count++
        }
        if count >= topK {
            break
        }
        if i2Start > 0 { //左移
            i2Start--
        } else { //上移
            i1Start--
        }

    }

    return maxHeap
}

func PushInt(maxHeap *[]int, node int) {
    *maxHeap = append(*maxHeap, node)
}

func PopInt(maxHeap *[]int) int {
    sort.Slice(*maxHeap, func(i, j int) bool {
        return (*maxHeap)[i] > (*maxHeap)[j]
    })
    ans := (*maxHeap)[len(*maxHeap)-1]
    *maxHeap = (*maxHeap)[0 : len(*maxHeap)-1]
    return ans
}

执行结果如下:

***

[左神java代码](https://github.com/algorithmzuo/coding-for-great-offer/blob/main/src/class18/Code04_TopKSumCrossTwoArrays.java)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档