b_pat_分享 & 链表排序 & 链表去重(链表模拟)

sharing


思路
照常输入,然后先遍历第一个链表,且将第一个链表的结点都的属性设置为访问过vis=true;再从第二条链表的开头开始遍历,遇到第一个vis=true的结点node则输出node.val,返回

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct node {
    int next=-1, vis;
} A[N];
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int s1,s2,n,addr,next;; cin>>s1>>s2>>n;
    char val;

    for (int i=0; i<n; i++) {
        cin>>addr>>val>>next;
        A[addr]={next, false};
    }
    for (int i=s1; i!=-1; i=A[i].next) A[i].vis=1;
    for (int i=s2; i!=-1; i=A[i].next) if (A[i].vis) {
        return printf("%05d", i), 0;
    }
    printf("-1");
    return 0;
}

Linked List Sorting

第一行首先包含一个整数 N,表示总节点数量,然后包含链表头节点的地址。
接下来 N 行,每行描述一个节点的信息,格式如下:
Address Key Next
其中 Address 是节点地址,Key 值是一个整数,Next 是下一个节点的地址。
现在,给出一个链表,请你按照 Key 值升序的顺序将链表重新排序。
思路
投机取巧将node全部弄到一个vector中排序,信誓旦旦地写啦,但打的时候忘记了这样排序A[i]的next还是原来的next(即未排序时的指向),所以输出的时候输出A[i+1]的addr

#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
struct node {
    int addr, val, next=-1;
} A[N];
bool cmp(node& a, node& b) {
    return a.val<b.val;
}
vector<node> l_sort(int head_addr) {
    vector<node> v; 
    for (int i=head_addr; i!=-1; i=A[i].next) {
        v.push_back(A[i]);
    }
    sort(v.begin(), v.end(), cmp);
    return v;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n,head_addr; cin>>n>>head_addr;
    for (int i=0; i<n; i++) {
        int addr, val, next; cin>>addr>>val>>next;
        A[addr]={addr, val, next};
    }
    auto v=l_sort(head_addr);
    if (v.empty()) {
        printf("0 -1");
    } else {
        printf("%d %05d\n", v.size(), v[0].addr);
        for (int i=0; i<v.size(); i++) {
            if (i==v.size()-1)  printf("%05d %d -1\n", v[i].addr, v[i].val);
            else                printf("%05d %d %05d\n", v[i].addr, v[i].val, v[i+1].addr);
        }
    }
    return 0;
}

Reversing Linked List

给定一个常数 K 和一个单链表 L,请你在单链表上每 K 个元素做一次反转,并输出反转完成后的链表。
如果链表最后一部分不足 K 个元素,则最后一部分不翻转。

思路
这题不能一边输入一边将节点push到vector中,因为你不知道哪个是头部结点,所以要输入完毕后再从头指针开始找结点

#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
struct node {
    int addr, val, next=-1;
} A[N];
void reverse_k(vector<node>& v, int l, int r) {
    while (l<r) {
        swap(v[l], v[r]);
        l++, r--;
    }
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int head_addr, n, k; cin>>head_addr>>n>>k;

    vector<node> v;
    for (int i=0; i<n; i++) {
        int addr,data,next; cin>>addr>>data>>next;
        A[addr]={addr,data,next};
    }    
    int p=head_addr;
    while (p!=-1) {
        v.push_back(A[p]);
        p=A[p].next;
    }
    for (int i=0; i+k-1<v.size(); i+=k) reverse_k(v,i,i+k-1);
    for (int i=0; i<v.size(); i++) {
        if (i==v.size()-1) printf("%05d %d -1\n", v[i].addr, v[i].val);
        else printf("%05d %d %05d\n", v[i].addr, v[i].val, v[i+1].addr);
    }
    return 0;
}

Deduplication on a Linked List

给定一个单链表 L,链表上的每个节点都存有一个键值,你应该删掉其中拥有重复键值绝对值的节点。
也就是说,对于每个值 K,只保留键值或键值绝对值为 K 的第一个节点。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct node {
    int addr, val, next=-1;
} A[N];
bool vis[N];
vector<node> ans;
vector<node> remove_and_get_dup(vector<node>& v) {
    vector<node> dup;
    for (int i=0; i<v.size(); i++) {
        if (vis[abs(v[i].val)]) {
            dup.push_back(v[i]);
        } else {
            vis[abs(v[i].val)]=1;
            ans.push_back(v[i]);
        }
    }
    return dup;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int head_addr, n; cin>>head_addr>>n;
    for (int i=0; i<n; i++) {
        int addr,data,next; cin>>addr>>data>>next;
        A[addr]={addr,data,next};
    }
    vector<node> v;
    int p=head_addr;
    while (p!=-1) {
        v.push_back(A[p]);
        p=A[p].next;
    }
    auto dup=remove_and_get_dup(v);
    for (int i=0; i<ans.size(); i++) {
        if (i!=ans.size()-1) printf("%05d %d %05d\n", ans[i].addr, ans[i].val, ans[i+1].addr);
        else printf("%05d %d -1\n", ans[i].addr, ans[i].val);
    }
    for (int i=0; i<dup.size(); i++) {
        if (i!=dup.size()-1) printf("%05d %d %05d\n", dup[i].addr, dup[i].val, dup[i+1].addr);
        else printf("%05d %d -1\n", dup[i].addr, dup[i].val);
    }
    return 0;
}

Splitting A Linked List

给定一个单链表,请编写程序将链表元素进行分类排列,使得所有负值元素都排在非负值元素的前面,而 [0,K] 区间内的元素都排在大于 K 的元素前面。
但每一类内部元素的顺序是不能改变的。
例如:给定链表为 18→7→-4→0→5→-6→10→11→-2,K 为 10,则输出应该为 -4→-6→-2→7→0→5→10→18→11
思路
用三个vector分别存各类元素最后的输出很麻烦,直接遍历3次原始vector更简单

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct node {
    int addr, val, next=-1;
} A[N];
vector<node> rearrange(vector<node>& v, int k) {
    vector<node> ans;
    for (int i=0; i<v.size(); i++) if (v[i].val<0) ans.push_back(v[i]);
    for (int i=0; i<v.size(); i++) if (v[i].val>=0 && v[i].val<=k) ans.push_back(v[i]);
    for (int i=0; i<v.size(); i++) if (v[i].val>k) ans.push_back(v[i]);
    return ans;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int head_addr, n, k; cin>>head_addr>>n>>k;
    for (int i=0; i<n; i++) {
        int addr,data,next; cin>>addr>>data>>next;
        A[addr]={addr,data,next};
    }
    vector<node> v;
    int p=head_addr;
    while (p!=-1) {
        v.push_back(A[p]);
        p=A[p].next;
    }
    auto ans=rearrange(v, k);
    for (int i=0; i<ans.size(); i++) {
        printf("%05d %d", ans[i].addr, ans[i].val);
        if (i!=ans.size()-1) printf(" %05d\n", ans[i+1].addr);
        else printf(" -1\n");
    }
    return 0;
}
posted @ 2020-09-24 21:31  童年の波鞋  阅读(218)  评论(0编辑  收藏  举报