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

// 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. CISCO实验记录八:ACL访问控制

    1.使用ACL实现免ping #access-list 100 deny icmp 192.168.0.1 0.0.0.0 192.168.1.2 0.0.0.0 #access-list 100 p ...

  2. 感知机和BP神经网络

    一.感知机 1.感知机的概念 感知机是用于二分类的线性分类模型,其输入是实例的特征向量,输出是实例的类别,类别取+1和-1二个值,+1代表正类,-1代表负类.感知机对应于输入空间(特征空间)中将实例分 ...

  3. Get Raster Properties获得栅格的信息

    Summary Returns the properties of a raster dataset. Usage The property returned will be displayed in ...

  4. Mybatis generator配置

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration ...

  5. java中json的使用和解析

    1.创建json对象 1.1 创建JSONObject对象 使用map初始化json @Test public void test1() { Map<String, Object> map ...

  6. linux之i2c子系统维护者源码仓库地址

    仓库地址: git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git

  7. SQL-W3School-高级:SQL UNION 和 UNION ALL 操作符

    ylbtech-SQL-W3School-高级:SQL UNION 和 UNION ALL 操作符 1.返回顶部 1. SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT ...

  8. CentOS源码安装 Tomcat/8.0.24

    依个人的习惯,喜欢将源码安装在/usr/local这个目录下面: 第一步:下载源码 wget http://archive.apache.org/dist/tomcat/tomcat-8/v8.0.2 ...

  9. C#与C++数据类型对应表(搜集整理一)

    C#与C++数据类型对应表(搜集整理一) C#与C++数据类型对应表   C#调用DLL文件时参数对应表 Wtypes.h 中的非托管类型 非托管 C 语言类型 托管类名 说明 HANDLE void ...

  10. kafka----简单的脚本命令重点

    kafka命令如下: kafka-shell基本命令 在节点hadoop-2,hadoop-3,hadoop-5,启动kafka 启动命令如下 kafka-server-start.sh /usr/l ...