更多题目可点链接:《 剑指offer》 目录索引
题目一
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。
思路:
时间复杂度为O(1),如果删除的非尾节点,采用替换法删除
如果是尾节点,采用一般删除
替换法删除的图解:https://blog.csdn.net/zhangye3017/article/details/78933001
代码:
#include<iostream>
using namespace std;
typedef int DataType;
typedef struct SListNode
{
DataType _data;
struct SListNode* _next;
}SListNode;
SListNode* BuyNode(DataType x)
{
SListNode* node = (SListNode*)malloc(sizeof(SListNode));
if (node != NULL)
{
node->_data = x;
node->_next = NULL;
}
return node;
}
void SListPushBack(SListNode** ppHead, DataType x)
{
SListNode* node = BuyNode(x);
if (*ppHead == NULL)
{
*ppHead = node;
}
else
{
SListNode* tail = *ppHead;
while (tail->_next)
{
tail = tail->_next;
}
tail->_next = node;
}
}
SListNode* FindNode(SListNode* list,DataType x)
{
SListNode* cur = list;
while (cur)
{
if (cur->_data == x)
{
return cur;
}
}
return NULL;
}
void SListPrint(SListNode* pHead)
{
SListNode* cur = pHead;
while (cur)
{
printf("%d ", cur->_data);
cur = cur->_next;
}
printf("\n");
}
void DeleteNode(SListNode** pListHead, SListNode* pToBeDeleted)
{
if (*pListHead == NULL || pToBeDeleted == NULL)
return;
if (pToBeDeleted->_next == NULL && *pListHead==pToBeDeleted)
{
//尾节点,且只有一个节点
free(*pListHead);
*pListHead = NULL;
}
else if (pToBeDeleted->_next==NULL)
{
//尾节点,且多个节点
SListNode* cur = *pListHead;
while (cur->_next != pToBeDeleted)
{
cur = cur->_next;
}
cur->_next = NULL;
free(pToBeDeleted);
pToBeDeleted = NULL;
}
else
{
//不是尾节点
SListNode* next = pToBeDeleted->_next;
pToBeDeleted->_data = next->_data;
pToBeDeleted->_next = next->_next;
free(next);
next = NULL;
}
}
void Test()
{
SListNode* list = NULL;
SListPushBack(&list, 1);
SListPushBack(&list, 2);
SListPushBack(&list, 3);
SListPushBack(&list, 4);
SListPushBack(&list, 5);
SListPushBack(&list, 6);
SListPushBack(&list, 7);
SListPrint(list);
DeleteNode(&list, FindNode(list, 1));
DeleteNode(&list, FindNode(list, 2));
DeleteNode(&list, FindNode(list, 3));
DeleteNode(&list, FindNode(list, 4));
DeleteNode(&list, FindNode(list, 5));
DeleteNode(&list, FindNode(list, 6));
DeleteNode(&list, FindNode(list, 7));
DeleteNode(&list, FindNode(list, -1));
SListPrint(list);
}
int main()
{
Test();
system("pause");
return 0;
}
题目二
在一个排序的链表中,如何删除重复的结点?例如:1,2,2,3,4,4,5,6 删除重复节点后为1,2,3,4,5,6
思路:
题目给出链表是有序的,故如果有重复的节点,一定是在当前节点的下一个
这里没有时间复杂度要求,可以采用常规删除法删除重复的节点
代码:
#include<iostream>
using namespace std;
typedef int DataType;
typedef struct SListNode
{
DataType _data;
struct SListNode* _next;
}SListNode;
SListNode* BuyNode(DataType x)
{
SListNode* node = (SListNode*)malloc(sizeof(SListNode));
if (node != NULL)
{
node->_data = x;
node->_next = NULL;
}
return node;
}
void SListPushBack(SListNode** ppHead, DataType x)
{
SListNode* node = BuyNode(x);
if (*ppHead == NULL)
{
*ppHead = node;
}
else
{
SListNode* tail = *ppHead;
while (tail->_next)
{
tail = tail->_next;
}
tail->_next = node;
}
}
SListNode* FindNode(SListNode* list, DataType x)
{
SListNode* cur = list;
while (cur)
{
if (cur->_data == x)
{
return cur;
}
}
return NULL;
}
void SListPrint(SListNode* pHead)
{
SListNode* cur = pHead;
while (cur)
{
printf("%d ", cur->_data);
cur = cur->_next;
}
printf("\n");
}
void DeleteDuplication(SListNode** pHead)
{
if (pHead == NULL || *pHead == NULL)
return;
SListNode* cur = *pHead;
SListNode* deletenode = NULL;
while (cur)
{
SListNode* next = cur->_next;
if (next!=NULL && cur->_data == next->_data)
{
//既然是排序过的链表,如果有重复的,必定重复的是当前节点的下一个
deletenode = next;
}
if (deletenode != NULL)
{
cur->_next = next->_next;
free(deletenode);
deletenode = NULL;
}
cur = cur->_next;
}
}
void Test()
{
//两个重复
SListNode* list = NULL;
SListPushBack(&list, 1);
SListPushBack(&list, 2);
SListPushBack(&list, 2);
SListPushBack(&list, 4);
SListPushBack(&list, 5);
SListPushBack(&list, 6);
SListPushBack(&list, 6);
DeleteDuplication(&list);
DeleteDuplication(&list);
SListPrint(list);
//没有重复
SListNode* list1 = NULL;
SListPushBack(&list1, 0);
SListPushBack(&list1, 2);
SListPushBack(&list1, 3);
SListPushBack(&list1, 4);
SListPushBack(&list1, 5);
SListPushBack(&list1, 6);
SListPushBack(&list1, 7);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
DeleteDuplication(&list1);
SListPrint(list1);
//只有一个不一样
SListNode* list2 = NULL;
SListPushBack(&list2, 1);
SListPushBack(&list2, 1);
SListPushBack(&list2, 1);
SListPushBack(&list2, 1);
SListPushBack(&list2, 1);
SListPushBack(&list2, 1);
SListPushBack(&list2, 2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
DeleteDuplication(&list2);
SListPrint(list2);
//全重复
SListNode* list3 = NULL;
SListPushBack(&list3, 1);
SListPushBack(&list3, 1);
SListPushBack(&list3, 1);
SListPushBack(&list3, 1);
SListPushBack(&list3, 1);
SListPushBack(&list3, 1);
SListPushBack(&list3, 1);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
DeleteDuplication(&list3);
SListPrint(list3);
}
int main()
{
Test();
system("pause");
return 0;
}