题目15 链表中倒数第K个节点
/////////////////////////////////////////////////////////////////////////////////////
// 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个节点的更多相关文章
- 面试题 15:链表中倒数第 k 个结点
面试题 15:链表中倒数第 k 个结点 题目:输入一个链表,输出该链表中倒数第 k 个结点.为了符合大多数人的习惯, 本题从 1 开始计数,即链表的尾结点是倒数第一个结点.例如一个有 6 个结点的 链 ...
- 15:链表中倒数第K个节点
/** * 面试题15:链表中倒数第K个节点 * 输入一个链表,输出该链表中倒数第k个结点. */ public class _15_linked_K { public static void mai ...
- 剑指offer-第三章高质量的代码(输出该链表中倒数第K个节点)
题目:输入一个链表,输出这个链表中倒数第K个节点.(代码的鲁棒性) 思路:用两个指针p1和p2,都指向头节点,开始的时候,p2不动,p1移动k-1次,指向第k个节点.此时,如果p1->next! ...
- 链表中倒数第k个节点(Java)
链表中倒数第k个节点 题目描述 输入一个链表,输出该链表中倒数第k个结点. 思路:two-pointers思想,因为是单链表,没法得prevous点,直接遍历得到链表长度再重新遍历效率很低. 采用双指 ...
- 《剑指offer》 链表中倒数第k个节点
本题来自<剑指offer> 链表中倒数第k个节点 题目: 输入一个链表,输出该链表中倒数第k个结点. 思路: 倒数第k个节点,而且只能访问一遍链表,定义两个节点,两者之间相差k个距离,遍历 ...
- 剑指offer(14)链表中倒数第K个节点
题目描述 输入一个链表,输出该链表中倒数第k个节点. 题目分析 用两个指针来跑,两个指针中间相距k-1个节点,第一个指针先跑,跑到了第k个节点时,第二个指针则是第一个节点. 这时候两个一起跑.当第一个 ...
- php实现求链表中倒数第k个节点
php实现求链表中倒数第k个节点 一.总结 $head = $head->next; //1.将$head节点next域里面的记录的那个地址值($head节点的下一个节点的地址)给$head,$ ...
- LeetCode 面试题22. 链表中倒数第k个节点
题目链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/ 输入一个链表,输出该链表中倒数第 ...
- 【剑指Offer】面试题22. 链表中倒数第k个节点
题目 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5.6. ...
随机推荐
- LOJ6436. 「PKUSC2018」神仙的游戏 [NTT]
传送门 思路 首先通过各种手玩/找规律/严谨证明,发现当\(n-i\)为border当且仅当对于任意\(k\in[0,i)\),模\(i\)余\(k\)的位置没有同时出现0和1. 换句话说,拿出任意一 ...
- Ubuntu 14.04 用户操作
新建用户sudo adduser linuxidc 修改hosts文件sudo gedit /etc/hosts ubuntu修改主机名sudo gedit /etc/hostname 删除用户在ro ...
- Raspberry Pi 4B 使用OpenCV访问摄像头picamera模块
目录 1.OpenCV安装 (1)安装依赖 (2)下载OpenCV源码 (3)安装pip (4)安装Python虚拟机 (5)编译OpenCV (6)验证安装 2.使用OpenCV和Python控制摄 ...
- fatal: unable to access 'https://github.com/Homebrew/brew/'
最近安装 Homebrew 遇到的坑,总结一下. 我的 Mac 版本是 10.13.6. 首先安装 Homebrew /usr/bin/ruby -e "$(curl -fsSL https ...
- 基本PSO算法实现(Java)
一.算法流程 Step1:初始化一群粒子(粒子个数为50个),包括随即位置和速度: Step2:计算每个粒子的适应度fitness: Step3:对每个粒子,将其适应度与其进过的最好位置(局部)pbe ...
- 20182332 实验一《Linux基础与Java开发环境》实验报告
20182332 实验一<Linux基础与Java开发环境>实验报告 课程:<程序设计与数据结构> 班级: 1823 姓名: 盛国榕 学号:20182332 实验教师:王志强 ...
- 关于IC电源管脚去耦电容
原文地址:https://mp.weixin.qq.com/s/0dAyTpAcQWXlYULqCeKgFA 每个集成电路(IC)都必须使用电容将各电源引脚连接到器件上的地,原因有二:防止噪声影响其本 ...
- Storm和Hadoop 区别
Storm - 大数据Big Data实时处理架构 什么是Storm? Storm是:• 快速且可扩展伸缩• 容错• 确保消息能够被处理• 易于设置和操作• 开源的分布式实时计算系统- 最初由Na ...
- 关于对多层嵌套的json字符串取目标值的问题
import java.util.HashMap;import java.util.Iterator;import java.util.Map;import net.sf.json.JSONObjec ...
- idea使用Snyk对项目进行安全漏洞审核、修复
笔者今天早上打开idea,看到右侧插件栏有一个大狗头,不懂什么时候好奇心驱使安装了这个插件.按图索骥,打开插件. 打开狗,里面会出现好多英文,其中有一处蓝色标底,here 字样的,你点击进去, 用Go ...