《暑假每日一题》Week 2:6.13 - 6.19

Day 1:4273. 链表合并

关键词:链表

题意:给定两个链表的首地址和 n 个结点,求合并后的链表,合并规则:从头每添加长链表中两个结点就要从锻炼表的末尾开始添加一个结点

图示:

思路:除非是面试中(你面前坐了一个面试官)链表题要真用链表来写,否则一般我们都用数组来对链表进行模拟,本题用 Vector 结合 Pair 存放每个结点的地址和数据,循环遍历进行合并,注意题目中未明确 a 链表一定是长链表,所以要判断进行交换

AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

#define x first
#define y second

using namespace std;

typedef pair<int,int> PII;

const int N = 100010;

int h1, h2, n;      //h1,h2分别为头地址, n为结点数

//数组模拟链表  
int v[N], ne[N];    //v[i] 存放 i 地址的结点的数据, ne[i] 存放 i 地址的结点的下一个结点地址

vector<PII> a,b;    //两个链表

int main( )
{
    cin >> h1 >> h2 >> n;
    //输入n个结点
    while(n --)
    {
        int adr, val, next;     //地址、数据、下一结点地址
        cin >> adr >> val >> next;
        v[adr] = val;
        ne[adr] = next;
    }

    //输入两个链表
    for(int i = h1; i != -1; i = ne[i]) a.push_back({i, v[i]});   
    for(int i = h2; i != -1; i = ne[i]) b.push_back({i, v[i]});
    
    //保证a为长的链表
    if(a.size() < b.size()) swap(a, b);

    vector<PII> c;              //合并后链表
    
    //合并链表
    for(int i = 0, j = b.size() - 1; i < a.size(); i += 2, j --)
    {
        c.push_back(a[i]);
        if(i + 1 < a.size())    c.push_back(a[i + 1]);
        if(j >= 0)  c.push_back(b[j]);
    }
    for(int i = 0; i < c.size(); i ++) 
    {
        if(i + 1 < c.size())
            printf("%05d %d %05d\n", c[i].x, c[i].y, c[i + 1].x);
        else
            printf("%05d %d -1\n", c[i].x, c[i].y);   
    }
    return 0;
}

Day 2 :4274. 后缀表达式

关键词:树的遍历

题意:给定几个结点组成一棵树,求其后缀表达式(后序遍历)

思路:用数组模拟树,首先要找到哪个是根结点,接着对根结点进行遍历,遍历分三种情况:

(1)存在左右子树:后序遍历,先左再右后根

(2)不存在左右子树,即当前结点为叶子结点:直接根

(3)只存在右结点,即当前结点为负号:先序遍历,先根再右

AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 25;

int n;                  //结点数

//数组模拟树
string v[N];
int l[N],r[N];     

bool st[N];             //判断结点是否有父结点

void dfs(int u)
{
    cout << '(';
    if (l[u] != -1 && r[u] != -1)   //若左右儿子都不为空,后序遍历
    {
        dfs(l[u]);
        dfs(r[u]);
        cout << v[u];
    }
    else if (l[u] == -1 && r[u] == -1)   //若左右儿子为空,即该结点为叶子
    {
        cout << v[u];   
    }
    else                            //左儿子为空,右儿子不为空,先序遍历
    {
        cout << v[u];
        dfs(r[u]);
    }
    
    cout << ')';
}

int main( )
{
    cin >> n;
    int data,left,right;
    for (int i = 1; i <= n; i ++)
    {
        cin >> v[i] >> l[i] >> r[i] ;       //输入i号结点的数据域,左儿子和右儿子
        if (left != -1 )    st[l[i]] = true;
        if (right != -1)    st[r[i]] = true;
    }
    
    int root;
    
    //寻找根节点,即没有父结点的结点
    for (int i = 1; i <= n; i ++)
        if (st[i] == false)
                root = i;
    
    dfs(root);     //深搜
    
    return 0;
}

Day 3:4275.Dijkstra序列

关键词:Dijkstra算法

题意:给定一个图和一个序列,判断求这个序列是否是Dijkstra序列。

思路:Dijkstra算法,找到一个尚未在集合内且与源顶点距离最小的顶点去判断

AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010, INF = 0x3f3f3f3f;

int n, m;
int dist[N], g[N][N];
bool st[N];
int q[N];

bool dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);
    dist[q[0]] = 0;
    for (int i = 0; i < n; i ++)
    {
        int t = q[i];
        for (int j = 1; j <= n; j++)
            if (!st[j] && dist[j] < dist[t])
                return false;
        st[t] = true;
        for (int j = 1; j <= n; j ++)
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }

    return true;
}

int main( )
{
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);
    while (m --)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = c;
    }

    int k;
    cin >> k;
    while (k --)
    {
        for (int i = 0; i < n; i ++)    cin >> q[i];
        if (dijkstra()) 
            puts("Yes");
        else
            puts("No");

    }    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值