《剑指Offer——在O时间删除链表结点,链表中倒数第k个结点》代码

Posted 穿迷彩服的鲨鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《剑指Offer——在O时间删除链表结点,链表中倒数第k个结点》代码相关的知识,希望对你有一定的参考价值。

@TOC


前言

//==================================================================
// 《剑指Offer——在O(1)时间删除链表结点,链表中倒数第k个结点》代码
// 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该
// 结点。
// ==================================================================
// 题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,
// 本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,
// 从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是
// 值为4的结点。
//==================================================================


一、示例

1.在O(1)时间删除链表结点

/*********************************************************************

/*
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动

示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

示例 2:
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
*/
***********************************************************************/

2.链表中倒数第k个结点

/******************************************************************************
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
*/
*************************************************************************/

二、代码解析

1.新建.cpp文件

代码如下(示例):

//==================================================================
// 《剑指Offer——在O(1)时间删除链表结点,链表中倒数第k个结点》代码
// 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该
// 结点。
// ==================================================================
// 题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,
// 本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,
// 从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是
// 值为4的结点。
//==================================================================



#include <iostream>
using namespace std;

struct ListNode
{
	int val;
	ListNode* next;
};


/*
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动

示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

示例 2:
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
*/
/*法一-------双指针----指向下一个删除*/
ListNode* deleteNode1(ListNode* head, int val)
{
	if (head->val == val)
	{
		return head->next;
	}
	ListNode* pNode = head;
	ListNode* cNode = head->next;
	while (cNode != nullptr && cNode->val != val)
	{
		pNode = cNode;
		cNode = cNode->next;
	}
	if (cNode != nullptr)
	{
		pNode->next = cNode->next;
	}

	return head;
}

/*法一-------双指针----下一个覆盖上一个删除*/
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
	if (!pListHead || !pToBeDeleted)
		return;

	// 要删除的结点不是尾结点
	if (pToBeDeleted->next != nullptr)
	{
		ListNode* pNext = pToBeDeleted->next;
		pToBeDeleted->val = pNext->val;
		pToBeDeleted->next = pNext->next;

		delete pNext;
		pNext = nullptr;
	}
	// 链表只有一个结点,删除头结点(也是尾结点)
	else if (*pListHead == pToBeDeleted)
	{
		delete pToBeDeleted;
		pToBeDeleted = nullptr;
		*pListHead = nullptr;
	}
	// 链表中有多个结点,删除尾结点
	else
	{
		ListNode* pNode = *pListHead;
		while (pNode->next != pToBeDeleted)
		{
			pNode = pNode->next;
		}

		pNode->next = nullptr;
		delete pToBeDeleted;
		pToBeDeleted = nullptr;
	}
}


/*
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
*/
/*法一---------双指针*/
ListNode* getKthFromEnd1(ListNode* head, int k)
{
	if (head == nullptr || k == 0)
	{
		return nullptr;
	}

	ListNode* pNode = head;
	for (int i = 0; i < k - 1; ++i)
	{
		if (pNode->next == nullptr)
		{
			return nullptr;
		}
		else
		{
			pNode = pNode->next;
		}
	}

	ListNode* tNode = head;
	while (pNode->next != nullptr)
	{
		pNode = pNode->next;
		tNode = tNode->next;
	}

	return tNode;
}

/*法二--------暴力*/
ListNode* getKthFromEnd2(ListNode* head, int k)
{
	ListNode* pNode = head;
	int len = 0;
	while (head)
	{
		++len;
		head = head->next;
	}

	if (k > len)
	{
		return nullptr;
	}

	for (int i = 0; i < len - k; ++i)
	{
		pNode = pNode->next;
	}

	return head;
}
int main()
{
	std::cout << "Hello World!\\n";
}

三,测试

以上是关于《剑指Offer——在O时间删除链表结点,链表中倒数第k个结点》代码的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer之在O时间删除链表节点

Java 剑指offer(17) 在O时间删除链表结点

剑指offer题目系列三(链表相关题目)

剑指offer18删除链表的(重复)节点

剑指Offer对答如流系列 - 在O时间删除链表结点

《剑指offer》第十八题:在O时间删除链表结点