【PTA刷题】求链式线性表的倒数第K项(代码+详解)

简介: 【PTA刷题】求链式线性表的倒数第K项(代码+详解)


题目

给定一系列正整数,请设计一个尽可能高效的算法,查找倒数第K个位置上的数字。

输入格式:

输入首先给出一个正整数K,随后是若干非负整数,最后以一个负整数表示结尾(该负数不算在序列内,不要处理)。

输出格式:

输出倒数第K个位置上的数据。如果这个位置不存在,输出错误信息NULL

输入样例:

4 1 2 3 4 5 6 7 8 9 0 -1

输出样例:

7

代码

#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构
struct ListNode {
    int val;
    struct ListNode* next;
};
// 查找倒数第K个位置上的数字
int findKthFromEnd(struct ListNode* head, int k) {
    if (!head || k <= 0) return -1; // 如果链表为空或k小于等于0,返回-1表示错误
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    // 快指针先移动k步
    for (int i = 0; i < k; ++i) {
        if (!fast) return -1; // 如果链表长度小于k,返回-1表示错误
        fast = fast->next;
    }
    // 同时移动慢指针和快指针,直到快指针到达链表尾部
    while (fast) {
        slow = slow->next;
        fast = fast->next;
    }
    return slow->val;
}
int main() {
    int k;
    scanf("%d", &k);
    int num;
    struct ListNode* head = NULL;
    struct ListNode* tail = NULL;
    // 构建链表
    while (scanf("%d", &num) && num >= 0) {
        struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
        newNode->val = num;
        newNode->next = NULL;
        if (!head) {
            head = newNode;
            tail = newNode;
        } else {
            tail->next = newNode;
            tail = newNode;
        }
    }
    int result = findKthFromEnd(head, k);
    if (result != -1) {
        printf("%d\n", result);
    } else {
        printf("NULL\n");
    }
    // 释放链表内存
    while (head) {
        struct ListNode* temp = head;
        head = head->next;
        free(temp);
    }
    return 0;
}

详解

这个问题要求找出一个正整数序列中倒数第K个元素的值。为了解决这个问题,代码使用了一个快慢指针的方法,并且用链表来存储输入的序列。下面是对这个算法和代码的详细解释:

算法逻辑

  1. 使用快慢指针:
  • 快指针 (fast) 和慢指针 (slow) 都从链表的头结点开始。
  • 先让快指针向前移动K步。这样,快慢指针之间就保持了K个节点的距离。
  • 然后,同时移动快指针和慢指针,直到快指针到达链表的末尾。此时,慢指针所在的位置就是倒数第K个节点。
  1. 边界条件处理:
  • 如果链表为空(head == NULL),或者K值不合理(k <= 0),函数直接返回-1,表示错误。
  • 如果链表长度小于K,也就是快指针在移动K步之前已经到达了链表末尾,函数同样返回-1。

代码解释

  1. 链表节点定义:
  • struct ListNode 定义了链表的节点结构,包括节点值 val 和指向下一个节点的指针 next
  1. 主函数 main:
  • 读取K值。
  • 通过循环读取输入的正整数,并构建链表。遇到负数时停止读取。
  • 调用 findKthFromEnd 函数来查找倒数第K个元素的值。
  1. 查找函数 findKthFromEnd:
  • 初始化快慢指针。
  • 让快指针先移动K步。
  • 同时移动快慢指针,直到快指针到达末尾。
  • 返回慢指针所指向的节点的值。
  1. 输出结果:
  • 如果返回值不是-1,则输出该值。
  • 如果返回值是-1,输出"NULL"。
  1. 释放内存:
  • 循环释放链表的每个节点,避免内存泄露。

这个算法的时间复杂度是O(n),因为它最多遍历链表两次:一次用于构建链表,一次用于找到倒数第K个元素。

目录
相关文章
|
存储 算法 C语言
【数据结构】树的基础知识及三种存储结构
文章目录 一、树的概念与定义 二、树的有关名词 三、树的存储结构 1.双亲表示法 2.孩子表示法 3.孩子兄弟表示法(又叫二叉树法) 四、树的应用
|
缓存 网络协议 应用服务中间件
NATAPP - 连不上 / 错误信息等问题解决汇总
NATAPP - 连不上 / 错误信息等问题解决汇总
3542 0
NATAPP - 连不上 / 错误信息等问题解决汇总
|
4月前
|
机器学习/深度学习 存储 大数据
在大数据时代,高维数据处理成为难题,主成分分析(PCA)作为一种有效的数据降维技术,通过线性变换将数据投影到新的坐标系
在大数据时代,高维数据处理成为难题,主成分分析(PCA)作为一种有效的数据降维技术,通过线性变换将数据投影到新的坐标系,保留最大方差信息,实现数据压缩、去噪及可视化。本文详解PCA原理、步骤及其Python实现,探讨其在图像压缩、特征提取等领域的应用,并指出使用时的注意事项,旨在帮助读者掌握这一强大工具。
265 4
|
8月前
|
传感器 人工智能 数据可视化
虚拟现实(VR)与增强现实(AR)的技术革新:塑造未来的沉浸式体验
【7月更文挑战第24天】VR和AR作为两种前沿的沉浸式技术,正以前所未有的速度改变着我们的世界。随着技术的不断革新和应用的不断拓展,我们有理由相信,未来的VR和AR将为我们带来更多令人惊叹的体验和技术革新。
|
6月前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
572 8
|
10月前
|
存储 算法 搜索推荐
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
295 1
|
10月前
|
C++
[C++/PTA] 使用成员函数重载复数类的运算符+
[C++/PTA] 使用成员函数重载复数类的运算符+
161 0
|
10月前
|
C++
【PTA】​ L1-009 N个数求和​ (C++)
【PTA】​ L1-009 N个数求和​ (C++)
388 0
【PTA】​ L1-009 N个数求和​ (C++)
|
SQL 数据库
关系数据库——关系操作和关系完整性
关系数据库——关系操作和关系完整性
340 0
|
SQL 监控 druid
Spring Boot 整合 Druid 指南
Spring Boot 整合 Druid 指南
37246 3