算法—寻找链表倒数第k个结点

题目

找出单向链表中的一个节点,该节点到尾指针的距离为K。链表的倒数第0个结点为链表的尾指针。要求时间复杂度为O(n)。
链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
}
链表节点的值初始化为1,2,3,4,5,6,7。
输入描述:
该节点到尾指针的距离K
输出描述:
返回该单向链表的倒数第K个节点,输出节点的值
示例1
输入:2
输出:6

备注:
请自觉实现一个链表,将1到7依次加入链表,然后再寻找倒数第K个节点。要求加节点与找节点的操作复杂度均为O(n)。

题目来源

小米2019秋招,测试开发岗

分析

有两种解题思路。
解法1:引入栈,将链表结点一一入栈,再出栈k个元素,即可找到链表的倒数第k个结点。

解法2:使用双指针,p1和p2相距k个结点,然后p1,p2都后移,当p1指向null时,p2指针正好指向倒数第k个结点。

思路如下图:
两种解题方法

方法1代码

import java.util.Stack;
import java.util.Scanner;
//import ListNode;

class ListNode{
    int m_nKey;   //节点值
    ListNode m_pNext=null;  //指针
    ListNode(int m_nKey){
        this.m_nKey=m_nKey;
    }
}

public class Main{
    public static ListNode FindKthToTail(ListNode listNode,int k){
        //寻找距尾指针的距离为K的节点值
        int count=1;    //i在后面计数时用到
        ListNode result=null; //result为返回的结果
        Stack<ListNode> stack=new Stack<>();  //引入栈空间
        while(listNode!=null){
            stack.push(listNode);  //将链表的数据一一入栈
            listNode=listNode.m_pNext;
        }
        //此时找距离尾指针为K的节点即是需要出栈K次得到的节点
        while(count<k){
            stack.pop();
            count=count+1;
        }
        if(!stack.isEmpty()){
            result=stack.pop();
        }
        return result;
    }
    public static void main(String args[]){
        //先构造节点为1-7的链表
        ListNode head=new ListNode(1); //头节点
        ListNode p=null;        //q为p的下一个节点
        ListNode q=null;
        p=head;
        for(int i=2;i<=7;i++){ //将剩余6个节点加入链表
            q=new ListNode(i);
            p.m_pNext=q;
            p=q;
            p.m_pNext=null;
        }
        Scanner sc=new Scanner(System.in);
        //System.out.println("请输入k值:");
        int k=sc.nextInt();
        ListNode result=FindKthToTail(head,k); //调用函数
        sc.close();
        System.out.println(result.m_nKey);
    }
}

方法2代码

import java.util.Stack;
import java.util.Scanner;
//import ListNode;

class ListNode{
    int m_nKey;   //节点值
    ListNode m_pNext=null;  //指针
    ListNode(int m_nKey){
        this.m_nKey=m_nKey;
    }
}

public class Main{
    public static ListNode FindKthToTail(ListNode pHead,int k){
        //寻找距尾指针的距离为K的节点值
        ListNode p1 = pHead;  //设置指针p1
        ListNode p2 = pHead;  //设置指针p2
        //指针p1与指针p2的间距为k
        int i=0;
        while(i < k){
            p1 = p1.m_pNext; //将p1指针后移
            i++;
        }
        while(p1 != null){
            p1 = p1.m_pNext;
            p2 = p2.m_pNext;
        }
        return p2;  //当p1指向null时,p2指向倒数第k个结点
    }
    public static void main(String args[]){
        //先构造节点为1-7的链表
        ListNode head=new ListNode(1); //头节点
        ListNode p=null;        //q为p的下一个节点
        ListNode q=null;
        p=head;
        for(int i=2;i<=7;i++){ //将剩余6个节点加入链表
            q=new ListNode(i);
            p.m_pNext=q;
            p=q;
            p.m_pNext=null;
        }
        Scanner sc=new Scanner(System.in);
        //System.out.println("请输入k值:");
        int k=sc.nextInt();
        ListNode result=FindKthToTail(head,k); //调用函数
        sc.close();
        System.out.println(result.m_nKey);
    }
}

代码结果

代码结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值