【算法与数据结构】19、LeetCode删除链表的倒数第 N 个结点

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解

一、题目

在这里插入图片描述

二、双指针法

  思路分析:这道题使用双指针一次遍历就能删除目标节点。快慢指针同一位置出发(虚节点),先让快指针前进n步,然后快慢指针一起更新,等到快指针到达链表末尾NULL指针时,慢指针指向倒数第n个节点,然后做删除操作要注意快指针指向NULL时,慢指针要指向删除节点的上一个节点,因此要让快指针多走一步
  程序如下

class Solution {
    
    
public:
	ListNode* removeNthFromEnd(ListNode* head, int n) {
    
    		
		ListNode* FakeNode = new ListNode(0, head);
		ListNode* Fastptr = FakeNode;
		ListNode* Slowptr = FakeNode;
		// 快慢指针确定相对位置
		while (n-- && Fastptr->next != NULL) Fastptr = Fastptr->next;
		Fastptr = Fastptr->next;		// 需要让fast指针再往前一步
		// 移动快慢指针,找到删除节点
		while (Fastptr != NULL) {
    
    
			Slowptr = Slowptr->next;
			Fastptr = Fastptr->next;
		}
		// 删除节点
		ListNode* tmp = Slowptr->next;	// 要删除的节点
		Slowptr->next = tmp->next;
		delete tmp;	// 手动释放内存
		return FakeNode->next;	// 返回头结点
	}	
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

三、完整代码

# include <iostream>
using namespace std;

struct ListNode {
    
    
	int val;
	ListNode* next;
	ListNode() : val(0), next(nullptr) {
    
    }
	ListNode(int x) : val(x), next(nullptr) {
    
    }
	ListNode(int x, ListNode* next) : val(x), next(next) {
    
    }
};

class Solution {
    
    
public:
	ListNode* removeNthFromEnd(ListNode* head, int n) {
    
    		
		ListNode* FakeNode = new ListNode(0, head);
		ListNode* Fastptr = FakeNode;
		ListNode* Slowptr = FakeNode;
		// 快慢指针确定相对位置
		while (n-- && Fastptr->next != NULL) Fastptr = Fastptr->next;
		Fastptr = Fastptr->next;		// 需要让fast指针再往前一步
		// 移动快慢指针,找到删除节点
		while (Fastptr != NULL) {
    
    
			Slowptr = Slowptr->next;
			Fastptr = Fastptr->next;
		}
		// 删除节点
		ListNode* tmp = Slowptr->next;	// 要删除的节点
		Slowptr->next = tmp->next;
		delete tmp;	// 手动释放内存
		return FakeNode->next;	// 返回头结点
	}	
};

ListNode* ChainGenerator(int arr[], int len) {
    
    
	ListNode* head = new ListNode(arr[0], NULL);
	ListNode* p = head;
	for (int i = 1; i < len; i++) {
    
    
		ListNode* pNewNode = new ListNode(arr[i], NULL);
		p->next = pNewNode; // 上一个节点指向这个新建立的节点
		p = pNewNode; // p节点指向这个新的节点
	}
	return head;
}

void my_print(ListNode* head, string str) {
    
    
	cout << str << endl;
	ListNode* cur = head;
	while (cur != NULL) {
    
    
		cout << cur->val << ' ';
		if (cur->next == NULL) break;
		cur = cur->next;
	}
	cout << endl;
}

int main()
{
    
    
	//int arr[] = { 1,2,3,4,5 };
	//int IndexFromEnd = 2;
	int arr[] = {
    
     1 };
	int IndexFromEnd = 1;
	int len = sizeof(arr) / sizeof(int);	
	Solution s1;
	ListNode* head = ChainGenerator(arr, len);
	my_print(head, "目标链表:");
	head = s1.removeNthFromEnd(head, IndexFromEnd);
	my_print(head, "删除目标元素后的链表:");
	system("pause");
	return 0;
}

end

猜你喜欢

转载自blog.csdn.net/qq_45765437/article/details/131150534