P1631 序列合并

题目描述

有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到 N^2N2 个和,求这 N^2N2 个和中最小的N个。

输入输出格式

输入格式:

第一行一个正整数N;

第二行N个整数 A_iAi , 满足 A_i\le A_{i+1}AiAi+1 且 A_i\le 10^9Ai109 ;

第三行N个整数 B_iBi , 满足 B_i\le B_{i+1}BiBi+1 且 B_i\le 10^9Bi109 .

【数据规模】

对于50%的数据中,满足1<=N<=1000;

对于100%的数据中,满足1<=N<=100000。

输出格式:

输出仅一行,包含N个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。

输入输出样例

输入样例#1:  复制
3
2 6 6
1 4 8
输出样例#1:  复制
3 6 7





每个组合数都必须有一个A序列的数和一个B序列的数

以A序列为例,每个数的第一个最优组合都是和B序列的第一个,开一个从小到大的优先队列,储存这n个数,每次弹出一个,第一次弹出的数所对应的B序列中的数必定是B序列中的第一个,那这个A序列中的数的最优组合就变成了加上B序列的第二个数(第一个数已经选过了),将这个数加入优先队列,出n个,就ok

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 100000 + 10;
int a[MAXN] , b[MAXN];
struct f
{
    int zhi;
    int node;

};
bool operator <(const f &a , const f &b)
{
    return a.zhi > b.zhi;
}

priority_queue<f> que;

int main()
{
    int n;
    cin >> n;
    for(int i = 1 ; i <= n ; i ++)
        scanf("%d" , &a[i]);
    for(int i = 1 ; i <= n ; i ++)
        scanf("%d" , &b[i]);
    for(int i = 1; i <= n ; i ++)
    {
        f temp;
        temp.zhi = a[i] + b[1];
        temp.node = 1;
        que.push(temp);
    }
    for(int i = 1; i <= n ; i ++)
    {
        f temp = que.top();
        que.pop();
        if(temp.node + 1 <= n)
        {
            f t;
            t.node = temp.node + 1;
            t.zhi = temp.zhi - b[temp.node] + b[temp.node + 1];
            que.push(t);
        }
        printf("%d" , temp.zhi);
        if(i != n)
            printf(" ");
    }
    return 0;
}

题目描述: 将两个有序链表合并一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 解题思路: 这道题可以使用递归和迭代两种方法来解决。 递归方法: 首先,如果两个链表一个是空链表,那么直接返回另一个链表即可。如果两个链表都不为空,则比较两个链表的头节点,将较小的那个节点作为合并后链表的头节点,并递归地将较小节点的 next 与另一个链表的头节点继续合并。最后返回合并后的链表头节点即可。 迭代方法: 首先,需要定义一个哑节点 dummy,用来表示合并后的链表的头节点。然后,定义一个指针 p,初始时指向 dummy 节点。接着,比较两个链表的头节点,将较小的那个节点插入到 p 的后面,并将 p 向后移动一位。最后,将较小节点所在的链表的头节点向后移动一位,并继续进行比较和插入操作,直到一个链表为空。最后,将另一个链表的剩余节点插入到合并后的链表的尾部,返回 dummy.next 即可。 代码实现: 递归方法: class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { if (!l1) return l2; if (!l2) return l1; if (l1->val < l2->val) { l1->next = mergeTwoLists(l1->next, l2); return l1; } else { l2->next = mergeTwoLists(l1, l2->next); return l2; } } }; 迭代方法: class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode* dummy = new ListNode(-1); ListNode* p = dummy; while (l1 && l2) { if (l1->val < l2->val) { p->next = l1; l1 = l1->next; } else { p->next = l2; l2 = l2->next; } p = p->next; } if (l1) p->next = l1; if (l2) p->next = l2; return dummy->next; } };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值