题目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. ...
随机推荐
- 网络1911、1912 C语言第4次作业--函数批改总结
目录 网络1911.1912 C语言第4次作业--函数批改总结 一.评分规则 二.本次作业亮点 三.本次作业存在的问题 四.助教有话说 五.得分详情 网络1911.1912 C语言第4次作业--函数批 ...
- Ubuntu 14.04 网卡网关配置修改
#添加网关route add default gw 192.168.5.1#强制修改网卡地址ifconfig eth0 192.168.5.40 netmask 255.255.255.0. 服务器需 ...
- Ubuntu 14.04 下安装redis后运行redis-cli 报出redis Connection refused错误【已解决】
在运行redis-cli运行后爆出错误,看了网上的都没有用例如:改ip,注释bind 127.0.0.1,或者是先运行./redis-server redis.conf,都没有用 只需要: 找到red ...
- Harmonious Graph
D. Harmonious Graph 好后悔在写这个题之前浪费了几分钟时间,不然我就写出来了.... 因为他就是连通块之间的合并问题,所以就用并查集就好了 复杂度好像也只是线性的吧... 然后就A了 ...
- AE开发之txt转shp
实现坐标txt文件转shp点集数据文件的窗体Form txt格式为:首行为“id,x,y” 第二行开始输入具体数值:id,x,y(x,y为具体的xy坐标) using System; using Sy ...
- docker安装Tomcat并部署war项目
转载:https://blog.csdn.net/javahighness/article/details/82859596 1进入容器 docker exec -it mytomcat bash 以 ...
- ROS indigo下Kinect v2的驱动安装与调试
ROS indigo下Kinect v2的驱动安装与调试 一.libfreenect2源码安装与测试 github地址:https://github.com/OpenKinect/libfreenec ...
- PYTHON -----pyinstaller的安装
这几天一直在安装pyinstaller库,发现了一个好方法 因为一直使用pip安装,我只能介绍一下pip安装pyinstaller的方法的注意事项 1:一般pip会在安装python的Scripts文 ...
- python 数字转字符保留几位小数 by gisoracle
#数字转字符保留几位小数 by gisoracle #数字转字符保留几位小数 by gisoracle def floattostr(num,xsnum): if xsnum==0: return s ...
- linux调用库的方式
linux调用库的方式有三种:1.静态链接库2.动态链接库3.动态加载库 其中1,2都是在编程时直接调用,在链接时加参数-l进行链接,运行时自动调用第三种需要在编程时使用dlopen等函数来获取库里面 ...