剑指offer-第三章高质量的代码(输出该链表中倒数第K个节点)

题目:输入一个链表,输出这个链表中倒数第K个节点。(代码的鲁棒性)

思路:用两个指针p1和p2,都指向头节点,开始的时候,p2不动,p1移动k-1次,指向第k个节点。此时,如果p1->next!=null,则同时移动P1和p2.直到p1指向最后一个节点。此时,P2指向倒数第k个节点。

C++代码:

#include<iostream>
using namespace std;
struct ListNode
{
    int m_nValue;
    ListNode* m_pNext;
};
ListNode* createList(int a[],int k)
{
    ListNode* pHead=NULL,*pNode=NULL;
    for(int i=0;i<k;i++)
    {
        ListNode* pNew=new ListNode();
        pNew->m_nValue=a[i];
        pNew->m_pNext=NULL;
        if(pHead==NULL)
        {
            pHead=pNew;
            pNode=pNew;
        }
        else
        {
            pNode->m_pNext=pNew;
            pNode=pNode->m_pNext;
        }
    }
    return pHead;
}
void printList(ListNode* pHead)
{
    ListNode* p=pHead;
    while(p!=NULL)
    {
        cout<<p->m_nValue<<" ";
        p=p->m_pNext;
    }
    cout<<endl;
}
ListNode* printKToTail(ListNode* pHead,unsigned int k)
{
    if(pHead==NULL||k==0)
        return NULL;
    ListNode* pAhead=pHead;
    ListNode* pTail=NULL;
    for(int i=0;i<k-1;i++)
    {
        if(pAhead->m_pNext!=NULL)
            pAhead=pAhead->m_pNext;
        else
            return NULL;
    }
    pTail=pHead;
    while(pAhead->m_pNext!=NULL)
    {
        pAhead=pAhead->m_pNext;
        pTail=pTail->m_pNext;
    }
    return pTail;
}
void main()
{
    int a[]={1,2,3,4,5};
    ListNode* pHead=createList(a,5);
    printList(pHead);
    ListNode* pKTail=printKToTail(pHead,2);
    cout<<pKTail->m_nValue<<endl;

}

Java代码:鲁棒性的体现:在这个函数printKToTail中,开头对头指针和k值进行判断,for语句中用if语句对总长度小于K值的时候做了判断。

public class PrintKToTail {

    public  static class ListNode
    {
        public int m_nValue;
        public ListNode m_pNext;
    }
    //创建链表
    public  static ListNode CreateLink(int a[],int k)
    {
        ListNode Head=null,q=null;
        for(int i=0;i<k;i++)
        {
            ListNode  pNew=new ListNode();
            pNew.m_nValue=a[i];
            pNew.m_pNext=null;
            if(Head==null)
            {
                Head=pNew;
                q=pNew;
            }
            else
            {
                q.m_pNext=pNew;
                q=q.m_pNext;
            }  

        }
        return Head;
    }
    //从头到尾打印列表
    public static  void printLink(ListNode pHead)
    {
        ListNode p=pHead;
        while(p != null)
        {
            System.out.print(p.m_nValue+" ");
            p=p.m_pNext;
        }
        System.out.println("\n");
    }
    //输出输出链表的倒数第K个节点
    public static ListNode printKToTail(ListNode pHead,int k)
    {
        if(pHead==null||k<=0)
            return null;
        ListNode pAhead=pHead;
        ListNode pTail=null;
        for(int i=0;i<k-1;i++)
        {
            if(pAhead.m_pNext!=null)
                pAhead=pAhead.m_pNext;
            else
                return null;
        }
        pTail=pHead;
        while(pAhead.m_pNext!=null)
        {
            pAhead=pAhead.m_pNext;
            pTail=pTail.m_pNext;
        }
        return pTail;
    }
    public static void main(String[] args)  

    {
        int a[]={1,2,3};
        ListNode  Head=CreateLink(a,3);
        printLink(Head);
        ListNode pKTail=printKToTail(Head,2);
        System.out.println(pKTail.m_nValue+" ");
    } 

}

相关题目1:求链表的中间节点。

思路:同样是定义两个指针p1和p2,两给指针同时移动,只是p1指针每次移动一步,p2指针每次移动两步,当p2指向链表的尾部时,p1正好指向中间节点。

相关题目2:判断一个单向链表是否为环状。

思路:同样是定义两个指正p1和p2,两个指针同时移动,当p2能追赶到p1时,表示该单向链表为环状。否则当p2已经走到尾部,而p1还没有追上p2.就代表改单向链表不为环状。

时间: 2024-12-27 12:34:08

剑指offer-第三章高质量的代码(输出该链表中倒数第K个节点)的相关文章

剑指offer—第三章高质量的代码(按顺序打印从1到n位十进制数)

题目:输入一个数字n,按照顺序打印出1到最大n位十进制数,比如输入3,则打印出1,2,3直到最大的3位数999为止. 本题陷阱:没有考虑到大数的问题. 本题解题思路:将要打印的数字,看成字符串,不足位的,高位补0.打印字符串的时候要对数字进行判断,不要将高位的0打印出来.打印字符串的结束条件是,当最高位产生进位时结束. c++代码: #include<iostream> using namespace std; //字符串模拟加法 bool Increment(char* number) {

剑指offer—第三章高质量代码(o(1)时间删除链表节点)

题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点,链表节点与函数的定义如下:struct ListNode{int m_nValue;ListNode* m_pValue;};void DeleteNode(ListNode** pListNode,ListNode * pToBeDeleted){} 思路:将要删除的节点的下一个节点的值赋值给i,删除下一个节点,但要考虑到删除的节点是最后一个节点并且该链表不止有一个节点的情况和该链表只有一个节点,该节点既是头节点也

剑指offer—第三章高质量代码(合并两个排序链表)

题目:输入员两个递增排序的链表,合并这两个链表并使新的链表中的结点仍然是按照递增排序的. 思路:首先,定义两个头节点分别为Head1和Head2的链表,然后比较第一个节点的值,如果是Head1->mValue比Head2->mValue小,那么头节点,就是Head1,递归实现后面的节点的排序. C++代码: #include<iostream> using namespace std; struct ListNode { int m_nValue; ListNode* m_pNex

剑指offer 链表中倒数第K个节点

利用两个间隔为k的指针来实现倒数第k个 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 /* struct ListNode {     int val;     struct ListNode *next;     ListNode(int x) :             val(x), next(NULL) {     } }; */ class Solution 

剑指OFFER之链表中倒数第k个节点(九度OJ1517)

题目描述: 输入一个链表,输出该链表中倒数第k个结点.(hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为两个整数n和k(0<=n<=1000, 0<=k<=1000):n代表将要输入的链表元素的个数,k代表要查询倒数第几个的元素.输入的第二行包括n个数t(1<=t<=1000000):代表链表中的元素. 输出: 对应每个测试案例,若有结果,输出相应的查找结果.否则,输出NULL. 样例输入: 5 2 1

22 链表中倒数第k个节点(第3章 高质量的代码-代码的鲁棒性)

题目描述: 输入一个链表,输出该链表中倒数第k个结点. 尾节点是倒数第一个节点 测试用例:   功能测试(第k个节点在中间.是头节点.是尾节点) 特殊输入测试(链表头节点是nullptr指针.链表的头节点个数小于k.k=0) 解题思路: 1)使用两个指针,一个指针先移动k步,如果链表小于k,终止返回nullptr.然后两个指针同时移动,知道后一个指针移出最后一个节点 //实现1/* struct ListNode { int val; struct ListNode *next; ListNod

剑指offer:链表中倒数第k个节点

题目描述输入一个链表,输出该链表中倒数第k个结点. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def FindKthToTail(self, head, k): # 由于k是从1开始的,因此需要特殊处理空链表和k<1的情况 if not head or k < 1: return None fast = head # 快指针先走k-1步 for _ in range(

剑指 14. 代码的鲁棒性 链表中倒数第k个结点

题目描述 输入一个链表,输出该链表中倒数第k个结点. 本人渣渣思路:要求解链表中的倒数第k个结点,可以采用栈先进后出的特点,倒数第k个进栈的话,出栈的时候就是第k个出栈的了 那么一开始就遍历链表,然后将每个结点进栈,在将栈的第k个结点出栈即可 import java.util.Stack;/*public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; }}*/public c

剑指:链表中倒数第k个节点

题目描述 输入一个链表,输出该链表中倒数第k个结点. 解法 pre 指针走 k-1 步.之后 cur 指针指向 phead,然后两个指针同时走,直至 pre 指针到达尾结点. 即cur与pre始终相距k-1. 当用一个指针遍历链表不能解决问题的时候,可以尝试用两个指针来遍历链表.可以让其中一个指针遍历的速度快一些. 此题需要考虑一些特殊情况.比如 k 的值小于 0 或者大于链表长度. package demo; public class Solution { public static clas