HJ51 输出单向链表中倒数第 k 个结点

HJ51 输出单向链表中倒数第 k 个结点

描述

输入一个单向链表,输出该链表中倒数第 k 个结点,链表的倒数第 1 个结点为链表的尾指针。
链表结点定义如下:

struct ListNode
{
int m_nKey;
ListNode * m_pNext;
};

正常返回倒数第 k 个结点指针,异常返回空指针.
要求:
(1)正序构建链表;
(2)构建后要忘记链表长度
数据范围:链表长度满足 1≤n≤1000 1≤n≤1000 , k≤n k≤n ,链表中数据满足 0≤val≤10000 0≤val≤10000

本题有多组样例输入。

输入描述:

输入说明
1 输入链表结点个数
2 输入链表的值
3 输入 k 的值

输出描述:

输出一个整数

示例 1

输入:
8
1 2 3 4 5 6 7 8
4
输出:
5

题解

顺序查找
import java.util.Scanner;
// 首先求出链表的长度 n,然后顺序遍历到链表的第 n - k个节点

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            // 1 输入链表结点个数
            // 2 输入链表的值
            // 3 输入k的值
            int n = in.nextInt();
            //  (1)正序构建链表;
            //  (2)构建后要忘记链表长度。
            //  生成链表
            ListNode head = new ListNode(-1);
            ListNode tmp = head;
            for (int i = 0; i < n; i++) {
                ListNode node = new ListNode(in.nextInt());
                tmp.m_pNext = node;
                tmp = tmp.m_pNext;
            }
            // k 的值
            int k = in.nextInt();
            if (getRes(head.m_pNext, k) != null) {
                System.out.println(getRes(head.m_pNext, k).m_nKey);
            } else {
                System.out.println(0);
            }

        }
    }
    public static ListNode getRes(ListNode node, int k) {
        int n = 0;// 长度
        ListNode res = null;// 结果节点
        for (res = node; res != null; res = res.m_pNext) {
            // 正向遍历 记录长度
            n++;
        }
        // 第 n-k 个节点
        if (k == 1 && n == 1) {
            return node;
        }
        res = node.m_pNext;
        for (int i = 2; i <= n - k; i++) {
            res = res.m_pNext;
        }
        return res;
    }
}
class ListNode {
    int m_nKey;
    ListNode  m_pNext;
    ListNode(int val) {
        this.m_nKey = val;
        m_pNext = null;
    }
}
快慢指针
import java.util.Scanner;
// 快慢指针
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt(); // 链表要接受的整数个数
            // 初始化 链表头节点
            ListNode head = new ListNode(-1);
            ListNode tmp = head;
            // 接收 node
            for (int i = 0; i < n; i++) {
                ListNode node = new ListNode(sc.nextInt());
                tmp.m_pNext = node;
                tmp = node;
            }
            // 接收 k
            int k = sc.nextInt();
            // 查找倒数第 k 个节点
            int val = getRes(head, k).m_nKey;
            System.out.println(val);
        }
    }
    public static ListNode getRes(ListNode head, int k) {
        if (head == null) {
            return null;
        }
        // 快指针 fast
        ListNode nodeA = head;
        // 慢指针
        ListNode nodeB = head;;
        // 快指针 移动到第k个节点
        for (int i = 0; i < k; i++) {
            if (nodeA == null) {
                return null;
            }
            nodeA = nodeA.m_pNext;
        }
        while (nodeA != null) {
            nodeA = nodeA.m_pNext;
            nodeB = nodeB.m_pNext;
        }
        return nodeB;
    }
}
// 链表
class ListNode {
    int m_nKey;
    ListNode m_pNext;
    ListNode (int m_nKey) {
        this.m_nKey = m_nKey;
        m_pNext = null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用双指针法,定义两个指针p1和p2,先让p1指向链表的头结点,然后让p2指向第k个结点。接着,同时移动p1和p2指针,直到p2指向链表的末尾,此时p1所指向的结点就是倒数第k个结点。 具体实现如下: 1. 定义两个指针p1和p2,初始时都指向链表的头结点。 2. 让p2指针先向后移动k-1个结点,如果链表长度小于k,则直接返回null。 3. 同时移动p1和p2指针,直到p2指向链表的末尾。 4. 返回p1指向的结点。 代码实现如下: public ListNode findKthToTail(ListNode head, int k) { if (head == null || k <= ) { return null; } ListNode p1 = head; ListNode p2 = head; for (int i = ; i < k - 1; i++) { if (p2.next != null) { p2 = p2.next; } else { return null; } } while (p2.next != null) { p1 = p1.next; p2 = p2.next; } return p1; } ### 回答2: 首先需要了解单向链表的结构和特点。单向链表由一个个节点组成,每个节点包括两部分:数据和指向下一个节点的指针。因此,单向链表每个节点只能访问其后面的节点,不能访问前面的节点。这就给查找倒数第k个节点带来了一定的难度。 假设单向链表的长度为n,则要查找倒数第k个节点,可以先让一个指针从链表的头节点开始向前移动k-1个位置,然后再让另一个指针从头节点开始一起向前移动,直到第一个指针到达链表末尾时,第二个指针(也就是倒数第k个节点)所指向的就是所求节点。 需要注意的是,在实际编程,要对链表的长度和k值进行一定的判断,防止出现链表长度不足k的情况。 下面是示例代码: ``` struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; ListNode* findKthToTail(ListNode* head, int k) { if (head == NULL || k == 0) return NULL; ListNode* pAhead = head; ListNode* pBehind = head; for (int i = 1; i < k; i++) { if (pAhead->next != NULL) { pAhead = pAhead->next; } else { return NULL; } } while (pAhead->next != NULL) { pAhead = pAhead->next; pBehind = pBehind->next; } return pBehind; } ``` 该函数的参数为单向链表头指针和 k 值,返回倒数第k个节点的指针。 ### 回答3: 首先我们可以想到两个指针p1、p2,先让p1指向链表的头结点,然后让它向后移动k-1个节点,接着让p2指向头节点,接下来p1、p2两个指针同时向后遍历,直到p1指向链表的末尾时,此时p2所指向的节点就是倒数第k个节点了。 具体实现如下: 1. 判断链表是否为空,如果为空则返回null; 2. 初始化p1和p2指向头节点; 3. 让p1向后移动k-1个节点; 4. 判断p1是否为空,如果为空则说明k的值太大,超出了链表的长度,返回null; 5. 接下来p1、p2两个指针同时向后遍历,直到p1指向链表的末尾时,此时p2所指向的节点就是倒数第k个节点了。 代码实现如下: ``` public ListNode findKthToTail(ListNode head, int k) { if(head == null || k == 0) { return null; } ListNode p1 = head; ListNode p2 = head; for(int i = 0; i < k-1; i++) { if(p1.next != null) { p1 = p1.next; } else { return null; // k的值太大,超出了链表的长度 } } while(p1.next != null) { p1 = p1.next; p2 = p2.next; } return p2; } ``` 以上就是输出单向链表倒数第k个节点的具体实现方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值