【面试题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. 10款很好用的 jQuery 图片滚动插件

    jQuery 作为最流行的 JavaScript 框架,使用简单灵活,同时还有许多优秀的插件可供使用.其中最令人印象深刻的应用之一就是各种很酷的图片效果,它可以让的网站更具吸引力.这里收集了10款很好 ...

  2. ListView Web 服务器控件概述(MSDN)

    1: "折叠"图像"展开"图像"复制"图像"复制悬停"图像 全部折叠全部展开 代码:全部 代码:多个 代码:Visual ...

  3. iOS网络加载图片缓存策略之ASIDownloadCache缓存优化

    iOS网络加载图片缓存策略之ASIDownloadCache缓存优化   在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用 ...

  4. C语言 数组输出,冒泡排序法,沉底排序法,二维数组输出,输出字母列长度,从随机数组中找重复数

    #include <stdio.h> #define sum 3+4//宏定义是原封不动的使用used for test4 #include <time.h>//used fo ...

  5. 如何解决win7系统访问共享服务器慢的问题

    最近重新装了win7系统,但发现当访问共享服务器的时候很慢,后来在网上搜索了相关解决办法,在此和大家分享下: 1. 通过“windows键”+“R键”快捷打开“运行”窗口,然后输入cmd命令敲回车,进 ...

  6. 《ISCSI集中存储》RHEL6——CE

    集中存储的作用: 服务端的多余的分区,客户端可以拿来存储数据,并且所存储的数据直接写在服务器的硬盘上,当客户端A崩溃时,其他客户端依旧可以从服务器端访问到客户端A存储的数据. 服务器配置: Iptab ...

  7. 一款jQuery仿海尔官网全屏焦点图特效代码

    一款jQuery仿海尔官网全屏焦点图特效代码,带有左右箭头的jQuery焦点图切换特效. 当焦点图切换时,下方的三块小图也相对应的进行切换.并且特效还兼容头疼的IE6.赶快去和谐了它吧! 适用浏览器: ...

  8. RGB颜色二值化

    原理:RGB颜色根据计算'灰度'的公式,可以转化为黑白2种颜色,实现二值化. 业务场景的应用:可以根据背景颜色,取一个黑色或白色的颜色,作为背景色上的文案字体颜色 具体代码: function get ...

  9. mysql删除、修改字段默认值

    alter table表名alter column字段名drop default; (若本身存在默认值,则先删除) alter table 表名 alter column 字段名 set defaul ...

  10. C#生成随机字符串

    //<summary> ///得到随机字符. ///</summary> ///<param name="intLength">Length o ...