Day4C链表的应用练习题

1 篇文章 0 订阅
1 篇文章 0 订阅

打印锯齿矩阵

锯齿矩阵是指每一行包含的元素个数不相同的矩阵,比如:

3 5 2 6

12 3 4

1 6 2 7

初始时矩阵为空,读入 m 对整数 (x,y),表示在第 x 行的末尾加上一个元素 y。

输出最终的锯齿矩阵。

输入格式

第一行输入两个整数 n,m (1≤n,m≤10000),其中 n 表示锯齿数组的行数,m表示插入的元素总数。

接下来一共 m 行,每行两个整数 x,y (1≤x≤n,0≤y≤10000),表示在第 x 行的末尾插入一个元素 y。

输出格式

一共输出 nn 行,每行若干个用空格分隔的整数。如果某行没有任何元素,则输出一个空行

格式说明

输出时每行末尾的多余空格,不影响答案正确性

样例输入
3 12
1 3
2 2
2 3
2 4
3 1
3 6
1 5
1 2
1 6
3 2
3 7
1 1
样例输出
3 5 2 6 1
2 3 4
1 6 2 7

我的答案

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

typedef struct Node {
    int data;
    struct Node *next;
} Node;

Node *create_node(int data) {
    Node *node = (Node *)malloc(sizeof(Node)); // 分配新节点的内存
    node->data = data;
    node->next = NULL;
    return node;
}

void insert(Node *head, int data) {
    Node *p = head;
    while (p->next != NULL) {
        p = p->next;
    }
    p->next = create_node(data); // 在链表末尾插入新节点
}

void print_list(Node *head) {
    Node *p = head->next; // 从第一个有效节点开始打印
    while (p != NULL) {
        printf("%d ", p->data); // 打印节点的数据
        p = p->next; // 移动到下一个节点
    }
    printf("\n");
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m); // 输入 n 和 m 的值
 
    Node *heads[MAXN]; // 创建一个节点指针数组
 
    // 初始化每个链表的头节点
    for (int i = 1; i <= n; i++) {
        heads[i] = create_node(-1); // 在数组中创建头节点
    }

    // 构建链表
    for (int i = 0; i < m; i++) {
        int x, y;
        scanf("%d%d", &x, &y); // 输入 x 和 y 的值
        insert(heads[x], y); // 在第x个链表中插入值为y的节点
    }
 
    // 打印链表
    for (int i = 1; i <= n; i++) {
        print_list(heads[i]); // 打印第i个链表
    }
 
    return 0;
}

2.求链表环的长度

  • 时间限制:1000ms
  • 内存限制:32867K
  • 语言限制:C语言

求出单链表中环的长度。我们已经为你定义好了链表结点。具体的可以参考注释部分。

传入的原始的链表的头指针。如果有环,返回环中结点的个数,否则返回 0。链表长度不大于 2000。

格式说明

输出时每行末尾的多余空格,不影响答案正确性

样例输入
  1. 6

  2. 8 13 11 20 2 8

  3. 2

样例输出
5
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
    int val;
    struct Node *next;
} ListNode;
int linkedListCycleLength(ListNode *head) {
    if (head == NULL || head->next == NULL) return 0;
    //判断链表是否为空或只有一个节点,如果是,则直接返回0,表示不存在环
    ListNode *slow = head; // 慢指针
    ListNode *fast = head; // 快指针
    
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next; // 慢指针移动一步
        fast = fast->next->next; // 快指针移动两步
        
        if (slow == fast) { // 慢指针和快指针相遇,表示有环
            int count = 1;
            slow = slow->next;

            while (slow != fast) {
                count++; // 统计环的长度
                slow = slow->next;
            }
            return count; // 返回环的长度
        }
    }
    return 0; // 没有环,返回0
}
int main() {
    int n;
    scanf("%d", &n);
    ListNode *head = (ListNode*)malloc(sizeof(ListNode));
    head->val = 0;
    head->next = NULL;
    ListNode *temp = head;
    for (int i = 0; i < n; ++i) {
        int x;
        scanf("%d", &x);
        temp->next = (ListNode*)malloc(sizeof(ListNode));
        temp->next->val = x;
        temp->next->next = NULL;
        temp = temp->next;
    }
    int d;
    scanf("%d", &d);
    ListNode *Nth = head;
    while (d--) {
        Nth = Nth->next;
    }
    temp->next = Nth;
    temp = head;
    head = head->next;
    free(temp);
    printf("%d\n", linkedListCycleLength(head));
    return 0;
}

找出两个链表的交点

  • 时间限制:1000ms
  • 内存限制:32867K
  • 语言限制:C语言

给出两个单链表,两个链表可能会相交。如下图,两个单链表在结点 2 相交。保证两个链表都不存在环。

我们已经为你定义好了链表结点。传入两个原始链表的头指针,返回交点的指针,如果两个链表没有交点那么返回NULL。链表总长度不大于 20000。

样例输入
5 3 2
样例输出
Accept

我的答案

ListNode* findIntersectionListNode(ListNode* headA, ListNode* headB) {
    // 初始化两个指针 pA 和 pB 分别指向链表 A 和链表 B 的头部
    ListNode* pA = headA;
    ListNode* pB = headB;
    
    // 遍历链表,直到 pA 和 pB 相遇或两者都到达各自链表的末尾
    while (pA != pB) {
        // 如果 pA 不为空,则将其指向下一个节点;否则将其指向链表 B 的头部
        pA = pA ? pA->next : headB;
        
        // 如果 pB 不为空,则将其指向下一个节点;否则将其指向链表 A 的头部
        pB = pB ? pB->next : headA;
    }
    
    // 返回交点,若无交点则返回 nullptr
    return pA;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值