C++单链表找倒数第k个节点(时间复杂度为o(n)哦,用相距k节点的2个指针进行操作)

//输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。
//我的思路是2个指针往后面找,你想啊,如果是一个指针,肯定需要遍历2次,第一个遍历总共节点数,第二次才遍历最终结果
//这样的做法明显是不够好的,时间复杂度变成了2n,但是如果我们用2个指针,他们之间的距离差k个节点,有一个节点到达NULL
//时(尾部),另一个节点就是我们要求的节点可以返回得到结果.

#include <iostream>
using namespace std;

template<typename T>
struct ListNode
{
  T m_nKey;//数据域
  ListNode* m_pNext;//指针域
	ListNode():m_nKey(T()),m_pNext(NULL){}
	ListNode(T value):m_nKey(value),m_pNext(NULL){}
};

template<typename T>
class List
{
	public:
	List()
	{
		head = new ListNode<T>();
	}
	void Insert(T value)
	{
		ListNode<T> *s = new ListNode<T>(value);
		s->m_pNext = head->m_pNext;//头插节点.
		head->m_pNext = s;
	}
  ListNode<T>* Find(int k)//寻找目标节点.
	{
		ListNode<T> *p = head;
		ListNode<T> *q = head;
		for(int i=0;i<k;i++)//让p指针先走一会儿(让子弹先飞一会儿).
		{
			p=p->m_pNext;
			if(p==NULL)
					return NULL;
		}
		while(p!=NULL)//此刻q,p再同时走,知道p走到结尾,然后返回q就是结果.
		{
			q=q->m_pNext;
			p=p->m_pNext;
		}
		return q;
	}
	T Getvalue(ListNode<T> *t)//根据节点来获取值,测试用.
	{
		return t->m_nKey;
	}
	private:
	ListNode<T> *head;
};

int main()
{
	List<int> list;
	int Item;
	while(cin>>Item,Item!=-1)
	{
		list.Insert(Item);
	}
	cout<<list.Getvalue(list.Find(4))<<endl;
	return 0;
}

时间: 2024-10-05 03:00:01

C++单链表找倒数第k个节点(时间复杂度为o(n)哦,用相距k节点的2个指针进行操作)的相关文章

查找单链表的倒数第k个值

刚开始,我想到的是一种笨方法,先遍历单链表,计算出单链表的长度len,然后再从头遍历单链表到第len-k个节点,那么 这个节点既是单链表的倒数第k个节点. 不过这种算法时间复杂度挺高的,还有一种更简单的方法,就是设置两个指针,分别指向单链表的头节点,然后让其中一个指针,先走k步, 之后,再让两个指针同时走,直到第一个指针走到单链表尾节点结束. 那么,第二个指针所指向的节点,就是倒数第k个节点. 代码如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1

【LeetCode-面试算法经典-Java实现】【019-Remove Nth Node From End of List(移除单链表的倒数第N个节点)】

[019-Remove Nth Node From End of List(移除单链表的倒数第N个节点)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a linked list, remove the nth node from the end of list and return its head. For example, Given linked list: 1->2->3->4->5, and n = 2. After remo

删除单链表中倒数第 k 个节点

思路 1 :两个指针 p1 ,p2 ,p1从头开始遍历,当 p1 到达第 k 个节点时,p2 开始: 当 P1 到达链表的最后一个节点时,p2 所指的节点则为链表中倒数第 k 个节点. public class Node{ public int data; public Node next; public Node(int data){ this.data = data; } public Node removeLastKNode(Node head,int k){ if(head == nul

C语言写单链表的创建、释放、追加(即总是在最后的位置增加节点)

昨天周末给学妹讲了一些指针的知识,本来我对指针就是似懂非懂的状态,经过昨天一讲,我对指针的学习就更深刻了果然给别人讲课也是学习的一个方法.加上最近复习数据结构,发现我的博客里没有链表的博文,所以趁这时候加上一篇. 在此之前,我们先谈一下我要说的一些基本知识: ①函数参数为什么是双指针? 我们先写一下这么一个程序: # include<stdio.h>void Gai(int m){ m=5;}int main(void){ int a=1; Gai(a); printf("%d\n&

C++获取单链表的倒数第k个节点

/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(pListHead == NULL || k == 0){ return NULL; } ListNode *pAhea

设A和B是两个按元素值递增有序的单链表,写一算法将A和B归并为按按元素值递减有序的单链表C,试分析算法的时间复杂度。(利用上篇带有头结点的线性链表操作)

#include <stdio.h>#include <malloc.h>typedef int DataType;#include "LinList.h" void main(){ SLNode *head_A,*head_B,*c,*pa,*pb,*pc; int i,j,x; ListInitiate(&head_A);//初始化链表a ListInsert(head_A,0,1);//a递增链表 ListInsert(head_A,1,3); L

算法总结之 在单链表和双链表中删除倒数第k个节点

分别实现两个函数,一个可以删除单链表中倒数第k个节点,另一个可以删除双链表中倒数第k个节点 思路: 如果链表为空,或者k<1 参数无效 除此之外 让链表从头开始走到尾,每移动一步,就让k的值减1 当链表走到头时候 如果k值大于0   说明不用调整  因为链表根本没有倒数第k个节点 此时将原链表直接返回即可 如果k值=0,说明链表倒数第k个节点就是头节点,此时直接返回head.next 也就是原链表的第二个节点 让第二个节点作为链表的头节点,此时直接返回head.next 如果k值<0  重新从

【C语言】单链表的相关热点面试题(包括:从尾到头打印,逆置,冒泡,寻找中间节点,倒数k节点)

从尾到头打印单链表 void FromTailToHeadPrint(SListNode*& head) {     stack<SListNode*> s;     SListNode* cur = head;     while (cur)     {         s.push(cur);         cur = cur->_next;     }     while (!s.empty())     {         cout << s.top()-&

[算法]在单链表和双链表中删除倒数第k个结点

题目: 分别实现两个函数,一个可以删除单链表中倒数第K个节点,另一个可以删除双链表中倒数第K个节点. 要求: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1). 解答: 让链表从头走到尾,每移动一步,就让K值减一,当链表走到结尾时,如果K值大于0,说明不用调整链表,因为链表根本没有倒数第K个节点,此时将原链表直接返回即可:如果K值等于0,说明链表倒数第K个节点就是头结点,此时直接返回head.next,相当于删除了头结点.当K的值小于零时,再次从头结点开始走,每移动一步,就让