找出单向链表的倒数第m个元素

简介:
链表节点:
None.gif class Node
ExpandedBlockStart.gif {
InBlock.gifpublic:
InBlock.gif    int        data;
InBlock.gif    Node*    next;
InBlock.gif
InBlock.gifpublic:
InBlock.gif    Node(int n) : data(n), next(0)
ExpandedSubBlockStart.gif    {
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    Node() : data(0), next(0)
ExpandedSubBlockStart.gif    {
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    Node* InsertAfter( int _data )
ExpandedSubBlockStart.gif    {
InBlock.gif        Node* newnode = new Node(_data);
InBlock.gif
InBlock.gif        newnode->next = next;
InBlock.gif        next = newnode;
InBlock.gif
InBlock.gif        return newnode;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
;


低效的查找算法:
None.gifNode* FindMToLastNode(Node* pHead,  int m)
ExpandedBlockStart.gif {
InBlock.gif    // 第一次遍历,获取链表的计数
InBlock.gif
    Node* pCurrent = pHead;
InBlock.gif    int nCount = 0;
InBlock.gif    while (pCurrent)
ExpandedSubBlockStart.gif    {
InBlock.gif        ++nCount;
InBlock.gif        pCurrent = pCurrent->next;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    // 防止越界
InBlock.gif
    if (m > nCount) return 0;
InBlock.gif
InBlock.gif    // 第二遍遍历,获取倒数第m个节点,也就是顺数滴n个节点
InBlock.gif
    int n = nCount - m + 1;
InBlock.gif    nCount = 0;
InBlock.gif    pCurrent = pHead;
InBlock.gif    while (pCurrent)
ExpandedSubBlockStart.gif    {
InBlock.gif        ++nCount;
InBlock.gif        if (nCount == n)
ExpandedSubBlockStart.gif        {
InBlock.gif            return pCurrent;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        pCurrent = pCurrent->next;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    return 0;
ExpandedBlockEnd.gif}
这个算法很低效,要循环列表两次,从时间上来说,消耗很大.从空间上,需要3个临时变量,消耗也有点大.


高效的查找算法:
None.gifNode* FindMToLastNode(Node* pHead,  int m)
ExpandedBlockStart.gif {
InBlock.gif    // 查找到第m个元素
InBlock.gif
    Node* pCurrent = pHead;
InBlock.gif    for (int i = 0; i < m; ++i)
ExpandedSubBlockStart.gif    {
InBlock.gif        if (pCurrent)
ExpandedSubBlockStart.gif        {
InBlock.gif            pCurrent = pCurrent->next;
ExpandedSubBlockEnd.gif        }

InBlock.gif        else
ExpandedSubBlockStart.gif        {
InBlock.gif            return NULL;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    // 一起继续遍历到链表尾部,
InBlock.gif    
// 现在pFind和pCurrent之间间隔了m个元素,
InBlock.gif    
// 所以,当pCurrent遍历到尾部的时候,
InBlock.gif    
// pFind就到了倒数第m个元素的位置上.
InBlock.gif
    Node* pFind = pHead;
InBlock.gif    while (pCurrent)
ExpandedSubBlockStart.gif    {
InBlock.gif        pFind        = pFind->next;
InBlock.gif        // 间隔m个元素
InBlock.gif
        pCurrent    = pCurrent->next;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    return pFind;
ExpandedBlockEnd.gif}
这个算法果然精妙!空间上只需要开销两个临时变量,时间上只需要循环链表一遍,也就是O(n)!
我太笨了,居然没有想到如此绝妙的算法.
目录
相关文章
|
12天前
19 删除链表的倒数第 N 个结点
19 删除链表的倒数第 N 个结点
|
1月前
|
算法
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
|
1月前
【数据结构】单链表之--无头单向非循环链表
【数据结构】单链表之--无头单向非循环链表
|
2月前
|
Java
Java移除链表元素
Java移除链表元素
26 0
【移除链表元素】LeetCode第203题讲解
【移除链表元素】LeetCode第203题讲解
|
1月前
|
存储 JavaScript
leetcode82. 删除排序链表中的重复元素 II
leetcode82. 删除排序链表中的重复元素 II
22 0
|
1月前
leetcode83. 删除排序链表中的重复元素
leetcode83. 删除排序链表中的重复元素
10 0
|
1月前
|
算法
常见算法题——203.移除链表元素
【2月更文挑战第9天】
23 0
|
2月前
|
算法 前端开发
删除排序链表中的重复元素 II
删除排序链表中的重复元素 II
13 0
|
2月前
|
算法 前端开发
删除排序链表中的重复元素
删除排序链表中的重复元素
17 0