/////////////////////////////////////////////////////////////////////////////////////

// 5. 题目15 链表中倒数第K个节点

//时间复杂度:O(n),空间复杂度O(n)

ListNode<int>* KthNodeFromEnd(ListNode<int>* pNode, int k)
{
if (pNode == NULL || k <= 0)
{
return NULL;
} ListNode<int>* p = pNode;
stack<ListNode<int>*> stStack; // 把链表数据全部压入栈
while (p)
{
stStack.push(p);
p = p->m_pNextNode;
} // 检查K的合法性
if (k > (int)stStack.size())
{
return NULL;
} while (!stStack.empty() && --k > 0)
{
stStack.pop();
} return stStack.top();
} // 方法二:倒序第K个元素 --> 正序(N - K)
//时间复杂度:O(n), 空间复杂度O(1) --> 需要遍历两次链表
ListNode<int>* KthNodeFromEnd_2(ListNode<int>* pNode, int k)
{
if (NULL == pNode || k <= 0)
{
return NULL;
} ListNode<int>* p = pNode;
int iNodeCount = 0; while (p)
{
iNodeCount++;
p = p->m_pNextNode;
} int iLoopCount = iNodeCount - k;
if (iLoopCount < 0)
{
return NULL;
} while (pNode && iLoopCount-- > 0)
{
pNode = pNode->m_pNextNode;
} return pNode;
} //方法三: 定义两个指针,两个指针之间相差(K-1),第一个指针遍历完,第二个指针指向的就是需要的节点
//时间复杂度:O(n),空间复杂度 : O(1) --> 只遍历一遍链表
ListNode<int>* KthNodeFromEnd_3(ListNode<int>* pNode, int k)
{
if (pNode == NULL || k <= 0)
{
return NULL;
} ListNode<int>* p1 = pNode;
ListNode<int>* p2 = pNode; while (p1 && p1)
{
if (--k < 0)
{
p2 = p2->m_pNextNode;
} p1 = p1->m_pNextNode;
} // K 超出了链表个数
if (k > 0 && p1 == NULL)
{
return NULL;
} return p2;
} // 扩展一:
// 求链表的中间节点,如果链表中节点数为奇数,返回中间节点,如果为偶数,返回中间两个的任意一个
// 声明两个指针:p1+1, p2+2 --> p1
// 时间复杂度: O(n),空间复杂度:O(1)
ListNode<int>* GetListMiddleNode(ListNode<int>* pNode)
{
if (NULL == pNode)
{
return NULL;
} ListNode<int>* p1 = pNode;
ListNode<int>* p2 = pNode; while (p1 && p2)
{
//这两个顺序不能变,否则链表个数为奇数时,P1会多移动一位!!!
// p2 + 2
if (!p2->m_pNextNode)
{
break;
} p2 = p2->m_pNextNode->m_pNextNode; // p1 + 1
p1 = p1->m_pNextNode;
} return p1;
} void KthNodeFromEndTestFunc()
{
cout << "\n\n --------------- KthNodeFromEndTestFunc Start -------------->" << endl; int aiArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int iLen = sizeof(aiArray) / sizeof(int);
TRAVERSAL_ARRAY(aiArray, iLen); CSingleList<int>* pList = new CSingleList<int>();
if (!pList)
{
return;
} for (int i = 0; i < iLen; i++)
{
pList->Insert(aiArray[i]);
}
pList->Traversal(); int k = 16;
cout << "方法一: 打印链表倒数第K个数: " << endl;
ListNode<int>* pKNode = KthNodeFromEnd(pList->GetHeadNode(), k);
if (pKNode)
{
printf("倒数第%d个值为: %d\n", k, pKNode->m_stData);
} cout << "方法二: 打印链表倒数第K个数: " << endl;
pKNode = KthNodeFromEnd_2(pList->GetHeadNode(), k);
if (pKNode)
{
printf("倒数第%d个值为: %d\n", k, pKNode->m_stData);
} cout << "方法三: 打印链表倒数第K个数: " << endl;
pKNode = KthNodeFromEnd_3(pList->GetHeadNode(), k);
if (pKNode)
{
printf("倒数第%d个值为: %d\n", k, pKNode->m_stData);
} cout << "扩展一: 打印链表中间节点: " << endl;
pKNode = GetListMiddleNode(pList->GetHeadNode());
if (pKNode)
{
printf("链表中间%d个值为: %d\n", iLen / 2, pKNode->m_stData);
} // 释放内存
SAVE_DELETE(pList); cout << "\n\n --------------- KthNodeFromEndTestFunc End -------------->" << endl; }

题目15 链表中倒数第K个节点的更多相关文章

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

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

  2. 15:链表中倒数第K个节点

    /** * 面试题15:链表中倒数第K个节点 * 输入一个链表,输出该链表中倒数第k个结点. */ public class _15_linked_K { public static void mai ...

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

    题目:输入一个链表,输出这个链表中倒数第K个节点.(代码的鲁棒性) 思路:用两个指针p1和p2,都指向头节点,开始的时候,p2不动,p1移动k-1次,指向第k个节点.此时,如果p1->next! ...

  4. 链表中倒数第k个节点(Java)

    链表中倒数第k个节点 题目描述 输入一个链表,输出该链表中倒数第k个结点. 思路:two-pointers思想,因为是单链表,没法得prevous点,直接遍历得到链表长度再重新遍历效率很低. 采用双指 ...

  5. 《剑指offer》 链表中倒数第k个节点

    本题来自<剑指offer> 链表中倒数第k个节点 题目: 输入一个链表,输出该链表中倒数第k个结点. 思路: 倒数第k个节点,而且只能访问一遍链表,定义两个节点,两者之间相差k个距离,遍历 ...

  6. 剑指offer(14)链表中倒数第K个节点

    题目描述 输入一个链表,输出该链表中倒数第k个节点. 题目分析 用两个指针来跑,两个指针中间相距k-1个节点,第一个指针先跑,跑到了第k个节点时,第二个指针则是第一个节点. 这时候两个一起跑.当第一个 ...

  7. php实现求链表中倒数第k个节点

    php实现求链表中倒数第k个节点 一.总结 $head = $head->next; //1.将$head节点next域里面的记录的那个地址值($head节点的下一个节点的地址)给$head,$ ...

  8. LeetCode 面试题22. 链表中倒数第k个节点

    题目链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/ 输入一个链表,输出该链表中倒数第 ...

  9. 【剑指Offer】面试题22. 链表中倒数第k个节点

    题目 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5.6. ...

随机推荐

  1. linux下文件传输一些方法整理.

    ftp类 ftp 命令已经不推荐使用了. #基本用法 lftp sftp://[domain name] lftp sftp://theURL.org #使用不同用户名 lftp sftp://[us ...

  2. MySQL数据分析-(3)MySQL软件的安装(Windows版)

    (一)MySQL下载 进入https://www.mysql.com/网页,找到DOWNLOADS然后点击进入页面,在页面中,我们选择社区版Community 点击,选择MySQL Community ...

  3. spring事物不回滚的问题

    学习spring分布式事务的时候,自己整了个demo,写test测试的时候发先事物没有回滚.此问题和分布式事务没关系.1.在service层引入@Transaction注解 使用 throw new ...

  4. 设置Python打印格式

    >>> def esc(code): ... return f'\033[{code}m' ... >>> print(esc('31;1;4') + 'reall ...

  5. EEPROM与FLASH

    最初的ROM rom最初不能编程,出厂什么内容就永远什么内容,不灵活.后来出现了prom,可以自己写入一次,要是写错了,只能换一片,自认倒霉. 人类文明不断进步,终于出现了可多次擦除写入的EPROM, ...

  6. Airbnb架构要点分享——阅读心得

    目前,Airbnb已经使用了大约5000个AWS EC2实例,其中大约1500个实例用于部署其应用程序中面向Web的部分,其余的3500个实例用于各种分析和机器学习算法.而且,随着Airbnb的发展, ...

  7. REGIONAL SCRUM GATHERING(RSG)2019 CHINA.

    欢迎参加 REGIONAL SCRUM GATHERING(RSG)2019 CHINA. 今年RSG将于2019年8月23号~24号,在北京新世界酒店举办.在为期2天的敏捷大会中,将有接近40位国内 ...

  8. powderdesinger显示中英文表名

     菜单->Tool->Model Options->Name Convention->右侧display中选择显示name还是code.不支持同时显示,但可以选择显示code, ...

  9. 以太坊 Geth 环境搭建(Ubuntu)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u014409380/article/details/79897335 时隔多日,我又想起来更新博客, ...

  10. 指定版本下载yum离线安装包

    #!/bin/bash releasever=7 for i in salt-minion salt-api salt-master docker-ce docker-ce-cli docker-co ...