• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >编程问答 > 两个递增排序的整数序列A,B,长度同为N,求前K个最小的a[i]+b[j]

两个递增排序的整数序列A,B,长度同为N,求前K个最小的a[i]+b[j]

作者:佚名 字体:[增加 减小] 来源:互联网 时间:2017-06-07

佚名通过本文主要向大家介绍了002835同为股份,同为股份,同为连接器,同为,同为数码科技有限公司等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
问题:两个递增排序的整数序列 A, B,长度同为N,求前K个最小的 a[i] + b[j]
描述:

递增排序的整数序列 A={a(i)}、B = {b(j)} 长度同为 N,两个数组相加得到 N2 个数,再对这些数进行排序,算法时间复杂度很高啊。有什么更好的办法吗?


解决方案1:

A B -> sort asc

i = 0, j = 0, k = 1;
while(k < K)
{
    if (A[i + 1] + B[j] < A[i] + B[j + 1]) then i++; else j++;
    k++;
}

解决方案2:

用小顶堆 应该可以减少一些时间复杂度. 不过我们可以试试用搜索的办法.

建立 大小为min(N, K)的一维数组A. 对应到二维来说, A[i] 表示 对第i行 的最右的被选的点. 如此可以把 解空间 分为(已选, 未选) 两部分. 这样判定 某点(x, y)是否被选, y <= A[i] 即被选中.
注:这里可以用 N x N的 状态矩阵 来理解, 标识 "两个数组相加得到 N2 个数" 的状态, x.y表示a[x]+b[y] 的状态. 初始化 M 为: M0.0 为 已选出, M0.1 和 M1.0 为 "待选", 其他为 "未选"

结果集R, 初始化为().

待选集S, 初始化为 (a0b0).

步骤:
1. 从 待选集S 中去掉最小的s, 把s加入 结果集R, 假设其为 a[i]+b[j];
2. 如果结果集 元素数量 = K, 退出;
2. 在M中找 Mi+1.j 和 Mi.j+1 的状态. 对某个Mx.y来说, 仅当Mx-1.y 和Mx.y-1 都为 "已选出", 才把axby加入待选集S; 使用状态数组 来确定 某个点的 状态.
3. 重复1.

时间复杂度: 待选集S 最大 为min(N, K+1). 选最小数可以用 小顶堆. 所以复杂度为 K*lg (min(N, K+1))

说明:

仅当Mx-1.y 和Mx.y-1 都为 "已选出", 才把axby加入待选集S -- 如果Mx-1.y 和Mx.y-1有一个为"待选"
或"未选", 则待选集S中必有元素 比axby 要小. 

写了java的实现, 这里 待选集 用了java内置的 PriorityQueue, 其基本操作都是logN的.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;

import org.junit.Test;

public class TopKSumOfTwoSortArrayFinderV2 {

    private PriorityQueue<Node> interSet;
    private List<Node> resultList;
    private int statusArray[];

    private static class Node implements Comparable<Node>{
        int indexX;
        int indexY;
        int value;

        public Node(int indexX, int indexY, int value) {
            this.indexX = indexX;
            this.indexY = indexY;
            this.value = value;
        }

        @Override
        public int compareTo(Node n) {
            return value - n.value;
        }

        @Override
        public String toString(){
            return "x:" + indexX + ", y:" + indexY + ", value:" + value;
        }
    }

    private void getTopKSum(int[] x, int[] y, int size, int K) {
        init(x, y, size, K);

        while(true){
            System.out.println("heap size: " + interSet.size());
            Node currentNode = interSet.poll();
            resultList.add(currentNode);
            int indexX = currentNode.indexX;
            int indexY = currentNode.indexY;
            select(indexX, indexY);
            printSelected(currentNode);
            if(resultList.size() >= K) break;

            if(indexX < size - 1){ // then currentNode has right node
                Node rightNode = new Node(indexX + 1, indexY, 
                        x[indexX + 1] + y[indexY]); 
                if( rightNode.indexY == 0 || ifSelected(indexX + 1, indexY - 1)){
                    // right node has not upper node or upper node is selected 
                    interSet.add(rightNode);
                }
            }
            if(indexY < size - 1){ // then currentNode has lower node
                Node lowerNode = new Node(indexX, indexY + 1, x[indexX] 
                        + y[indexY + 1]); 
                if( lowerNode.indexX == 0 || ifSelected(indexX - 1, indexY + 1)){
                    // lower node has not left node or left node is selected 
                    interSet.add(lowerNode);
                }
            }
        }
    }

    private void printSelected(Node n) {
        System.out.println("selected: " + n);
    }

    private void select(int x, int y){
        if(y > statusArray[x])
            statusArray[x] = y;
    }

    private boolean ifSelected(int x, int y){
        return y <= statusArray[x];
    }

    private void init(int[] x, int[] y, int size, int k) {
        statusArray = new int[size > k ? size : k];
        Arrays.fill(statusArray, -1);

        interSet = new PriorityQueue<>(size);
        interSet.add(new Node(0, 0, x[0] + y[0]));

        resultList = new ArrayList<>();
    }

    @Test
    public void test(){
        int[] a={1,2,3,4,5,6,7,8};
        int[] b={100,200,300,400,500,600,700,800};
        getTopKSum(a, b, 8, 40);
    }
}

解决方案3:

数据集定义

谢谢 @brayden 提供的思路。

将M(n*n)矩阵分为三个区域:

  • 已经遍历 && 已经选择(结果集R)
  • 已经遍历 && 未选择(待选集S, 使用最小堆结构),
  • 未遍历(待遍历集U)

操作

  1. 初始化,将(a0b0)放到S集(最小堆)
  2. 从S 集删除最小元素(即堆顶),最小元素放到R 结果集。(如果R足够K, 就结束)
  3. 从待遍历集U中, 选出可能是下一个或者两个 能进入R的 小元素, 放到S集中
  4. 回到步骤2 继续

长度单位大小排序,长度为n的线性表排序,哈希排序平均查找长度,冒泡排序,excel排序,快速排序,选择排序,排序算法,希尔排序,排序题,基数排序,拓扑排序,归并排序,表格排序,排序函

复杂度

S集最多为min(K, n). 所以时间复杂度为O(K*log(min(K, n)))

代码示例

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct heap{
    int ai,bi;
    int v;
};
int S_n= 0;

void print_heap(struct heap *S){
    int i=0,j=0;
    int pad = (int)log2((float)S_n);
    int k = 1;
    printf("\n---- print S start --------\n");
    while(i<S_n){
        for(j=0; j<pad;j++){
            printf("%8c", ' ');
        }
        for(j = i+k; i<j && i<S_n; i++){
            printf("%-2d(%d,%d)\t\t", S[i].v, S[i].ai, S[i].bi);
        }
        printf("\n");
        k *=2;
        pad--;
    }
    printf("\n---- print S end --------\n");
}
void heap_swap(struct heap *a, struct heap *b){
    struct heap t;
    t=*a;
    *a=*b;
    *b=t;
}

/**
 * 向下调整堆: O(logN)
 */
void min_heap_down(struct heap *S, int i){
    int left,right;
    while(2*i+1<S_n){
        int mini;
        left = 2*i+1;
        right = left+1;
        mini = left;
        if(right < S_n && S[right].v < S[left].v){
            mini = right;
        }
        if(S[mini].v < S[i].v){
            heap_swap(S+mini, S+i);
            i = mini;
        }else{
            break;
        }
    }
}
/**
 * min_heap_insert: O(logN)
 */
void min_heap_insert(struct heap *S, int ai, int bi, int v){
    int i,j,temp;
    struct heap node = {ai, bi, v};
    S[S_n] = node;
    i = S_n;
    while(i > 0){
        j = (i-1)/2;
        if(S[j].v > S[i].v){
            heap_swap(S+i, S+j);
        }else{
            break;
        }
        i = j;
    }   
    S_n++;
}

/**
 * min_heap_del: O(logN)
 */
void min_heap_del(struct heap *S, int i){
    heap_swap(&S[i], &S[--S_n]);
    min_heap_down(S, i);
}

/**
 * topK of [a + b]
 */
int topK(int *a, int *b, int n, int K, int *R){
    int k=0;
    struct heap *S;
    S = malloc( sizeof(struct heap) * (K<n ? K :n));

    min_heap_insert(S, 0, 0, a[0]+b[0]);

    int i,j;
    while(S_n >0){
        struct heap node = S[0];
        min_heap_del(S, 0);
        R[k] = node.v;
        printf("Result: %d k=%d\n", node.v, k);

        if(++k < K){
            if(node.bi + 1 < n){
                min_heap_insert(S, node.ai, node.bi+1, a[node.ai] + b[node.bi+1]);
            }
            if(node.bi == 0 && node.ai+1 < n){
                min_heap_insert(S, node.ai+1, 0, a[node.ai+1] + b[0]);
            }
        }else{
    



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 两个递增排序的整数序列A,B,长度同为N,求前K个最小的a[i]+b[j]

相关文章

  • 2017-06-07 请教个pdDtataFrame的问题
  • 2017-06-07 jbpm使用mysql导出问题?
  • 2017-06-07 七牛资源间歇性无法访问
  • 2017-06-07 易语言操作七牛云获取上传进度
  • 2017-06-07 jbpm的疑惑,和JBPMprocessInstance表的作用
  • 2017-06-07 VMWare10安装109MacOS如何调整分辨率为19201200?
  • 2017-06-07 testeax,eax和cmpeax,0有什么区别吗?
  • 2017-06-07 redis可以实现类似mysql的高级排序吗?
  • 2017-06-07 什么情况下七牛触发分片上传?
  • 2017-06-07 另一重量级云存储今天提供图片处理服务啦

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • (flask)关于jinjia模板语法的两个疑惑
    • 用scrapy爬虫结合什么第三方解析js动态加载网页比较好?
    • 请求解决VFP人工事务修改SQL数据的问题
    • 七牛镜像云存储的爬虫名称是什么?
    • 身份认证页面有错误!无法上传身份证图片
    • python获取某个值在list中的位置?
    • 谁懂JSP,求教
    • 使用视频转码服务时返回错误。
    • JBossAS7写一个简单的webservice
    • android七牛返回的body中的filename通过什么可以修改

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有