题目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; }