【面试题015】链表中倒数第k个结点 

 

可以用两个指针,当第一个指针指向了第k个时候,第二个指针让他指向链表的第一个元素,然后这两个指针同时向后面移动,

当第一个指针移动到末尾的时候,第二个指针指向的就是倒数第K个结点;两个指针的间距保持为k-1;

当我们遍历列表的时候发现用一个指针是解决不了问题的,我们可以尝试用两个指针来解决问题,

一个指针走的比另外一个指针走得快一点,或者先让其中的一个指针走了若干步,然后再让第二个指针来走;

kth.cpp:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 
#include <iostream>
#include <cstdio>
#include "List.h"

ListNode *FindKthToTail(ListNode *pListHead, unsigned int k)
{
    if(pListHead == NULL || k == 0)
    {
        return NULL;
    }

ListNode *pAhead = pListHead;
    ListNode *pBehind = NULL;

for(unsigned int i = 0; i < k - 1; ++i)
    {
        if(pAhead->m_pNext != NULL)
        {
            pAhead = pAhead->m_pNext;
        }
        else
        {
            return NULL;
        }
    }

pBehind = pListHead;
    while(pAhead->m_pNext != NULL)
    {
        pAhead = pAhead->m_pNext;
        pBehind = pBehind->m_pNext;
    }
    return pBehind;
}

// 测试要找的结点在链表中间
int main()
{
    printf("=====Test1 starts:=====\n");
    ListNode *pNode1 = CreateListNode(1);
    ListNode *pNode2 = CreateListNode(2);
    ListNode *pNode3 = CreateListNode(3);
    ListNode *pNode4 = CreateListNode(4);
    ListNode *pNode5 = CreateListNode(5);

ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

printf("expected result: 4.\n");
    ListNode *pNode = FindKthToTail(pNode1, 2);
    PrintListNode(pNode);

DestroyList(pNode1);
    return 0;
}

运行结果:

=====Test1 starts:=====
expected result: 4.
The key in node is 4.
请按任意键继续. . .

List.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
#ifndef _LIST_H_
#define _LIST_H_

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

ListNode *CreateListNode(int value);
void ConnectListNodes(ListNode *pCurrent, ListNode *pNext);
void PrintListNode(ListNode *pNode);
void PrintList(ListNode *pHead);
void DestroyList(ListNode *pHead);
void AddToTail(ListNode **pHead, int value);
void RemoveNode(ListNode **pHead, int value);

#endif //_LIST_H_

List.cpp:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 
#include "list.h"
#include <stdio.h>
#include <stdlib.h>

ListNode *CreateListNode(int value)
{
    ListNode *pNode = new ListNode();
    pNode->m_nValue = value;
    pNode->m_pNext = NULL;

return pNode;
}

void ConnectListNodes(ListNode *pCurrent, ListNode *pNext)
{
    if(pCurrent == NULL)
    {
        printf("Error to connect two nodes.\n");
        exit(1);
    }

pCurrent->m_pNext = pNext;
}

void PrintListNode(ListNode *pNode)
{
    if(pNode == NULL)
    {
        printf("The node is NULL\n");
    }
    else
    {
        printf("The key in node is %d.\n", pNode->m_nValue);
    }
}

void PrintList(ListNode *pHead)
{
    printf("PrintList starts.\n");

ListNode *pNode = pHead;
    while(pNode != NULL)
    {
        printf("%d\t", pNode->m_nValue);
        pNode = pNode->m_pNext;
    }

printf("\nPrintList ends.\n");
}

void DestroyList(ListNode *pHead)
{
    ListNode *pNode = pHead;
    while(pNode != NULL)
    {
        pHead = pHead->m_pNext;
        delete pNode;
        pNode = pHead;
    }
}

void AddToTail(ListNode **pHead, int value)
{
    ListNode *pNew = new ListNode();
    pNew->m_nValue = value;
    pNew->m_pNext = NULL;

if(*pHead == NULL)
    {
        *pHead = pNew;
    }
    else
    {
        ListNode *pNode = *pHead;
        while(pNode->m_pNext != NULL)
            pNode = pNode->m_pNext;

pNode->m_pNext = pNew;
    }
}

void RemoveNode(ListNode **pHead, int value)
{
    if(pHead == NULL || *pHead == NULL)
        return;

ListNode *pToBeDeleted = NULL;
    if((*pHead)->m_nValue == value)
    {
        pToBeDeleted = *pHead;
        *pHead = (*pHead)->m_pNext;
    }
    else
    {
        ListNode *pNode = *pHead;
        while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)
            pNode = pNode->m_pNext;

if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value)
        {
            pToBeDeleted = pNode->m_pNext;
            pNode->m_pNext = pNode->m_pNext->m_pNext;
        }
    }

if(pToBeDeleted != NULL)
    {
        delete pToBeDeleted;
        pToBeDeleted = NULL;
    }
}

Makefile:

1
2
3
4
5
6
7
8
9
10
11
12
 
.PHONY:clean  
CPP=g++  
CFLAGS=-Wall -g  
BIN=test  
OBJS=Kth.o List.o  
LIBS=  
$(BIN):$(OBJS)  
    $(CPP) $(CFLAGS) $^ -o $@ $(LIBS)  
%.o:%.cpp  
    $(CPP) $(CFLAGS) -c $< -o $@  
clean:  
    rm -f *.o $(BIN)  

【面试题015】链表中倒数第k个结点的更多相关文章

  1. 面试题 15:链表中倒数第 k 个结点

    面试题 15:链表中倒数第 k 个结点 题目:输入一个链表,输出该链表中倒数第 k 个结点.为了符合大多数人的习惯, 本题从 1 开始计数,即链表的尾结点是倒数第一个结点.例如一个有 6 个结点的 链 ...

  2. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

  3. 剑指offer-面试题15.链表中倒数第k个结点

    题目:输入一个链表,输出该链表的倒数第K个结点.为了符合大多数人的习惯,本题 从1开始计数,即链表的尾结点是倒数第1个节点.例如有一个链表有6个节点,从 头节点开始他们的值依次是1,2,3,4,5,6 ...

  4. 面试题一 链表中倒数第k个结点

    void findLastK(LinkedNode head, int k, int n){ if (head == NULL || k == 0) return; LinkedNode t1 = h ...

  5. 【剑指Offer面试题】 九度OJ1517:链表中倒数第k个结点

    鲁棒性是指程序可以推断输入是否符合规范要求,并对不和要求的输入予以 合理的处理. 题目链接地址: http://ac.jobdu.com/problem.php?pid=1517 题目1517:链表中 ...

  6. 【剑指offer】面试题 22. 链表中倒数第 K 个节点

    面试题 22. 链表中倒数第 K 个节点

  7. (剑指Offer)面试题15:链表中倒数第k个结点

    题目: 输入一个链表,输出该链表中倒数第k个结点. 例如:链表中有6个结点,从头到尾依次为1,2,3,4,5,6,则该链表的倒数第3个结点为4. 链表结点定义: struct ListNode{ in ...

  8. P107、面试题15:链表中倒数第K个结点

    题目:输入一个链表,输出该链表中倒数第K个结点.为了符合大多数人的习惯,本体从1开始奇数,即链表的尾结点是倒数第1个结点.例如一个链表有6个结点,从头结点开始他们的值一次是1.2.3.4.5.6.这个 ...

  9. 面试题15:链表中倒数第K个结点

    输入一个链表,输出该链表中倒数第k个结点. 方法1: 这个解法要循环两次链表 /* public class ListNode { int val; ListNode next = null; Lis ...

随机推荐

  1. Debug Intro

    The ABAP Debugger is used tool to execute and analyze programs line by line. Using it we can check t ...

  2. Python单元测试——深入理解unittest (转)

    单元测试的重要性就不多说了,可恶的是Python中 有太多的单元测试框架和工具,什么unittest, testtools, subunit, coverage, testrepository, no ...

  3. HTML5-Video & Audio

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. centos 减少tty数量的方法

    在linux中,包括本文介绍的centos系统中,tty系统默认是给出7个,前六个是terminal,一个用于X. 在centos5.x中减少tty数量,通过修改/etc/inittab来实现. [r ...

  5. 跨域名设置cookie或获取cookie

    可以使用jquery里面的ajax中的jsonp的方式来访问就可以了.代码如下: $.ajax({ url: 'your url', data: {'xx' : 'xx', 'xx2' : 'xx2' ...

  6. opencv的初体验

    http://guoming.me/opencv-config  这篇文章有讲解opencv的安装与配置 一些常用库 opencv_core249d.lib opencv_imgproc249d.li ...

  7. EAI概述

    企业的业务流程同时会涉及多个应用系统,因此要求这些系统能够协同,但接口,架构的不统一往往使得这些本应紧密集成的应用系统成了一个个“信息孤岛”.于是,企业应用集成(Enterprise Applicat ...

  8. Python支持中文注释

    三处设置,使Python的Eclipse开发环境(使用PyDev)支持中文 - (a)Eclipse的Window菜单Editors设置: Eclipse工具条 -> Window -> ...

  9. Java 包(package)详解

    为了更好地组织类,Java提供了包机制,用于区别类名的命名空间. 包的作用 1 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用. 2 如同文件夹一样,包也采用了树形目录的存储方式.同一 ...

  10. HTTP报文格式

    请求报文 <method><SP><uri><SP><version><CRLF> <head-name><: ...