<1.简单:
移除链表元素(来源力扣)
合并两个有序链表(来源力扣)
反转链表(来源力扣)
链表的中间结点(来源力扣)
链表中倒数第k个结点(来源牛客)OJ链接:链表中倒数第k个结点_牛客题霸_牛客网
<2.较难:
链表分割(来源牛客)OJ链接:链表分割_牛客题霸_牛客网
链表的回文结构 (来源牛客)OJ链接:链表的回文结构_牛客题霸_牛客网
///
1移除链表元素:
解题思路:创建哨兵位,把不是val的节点拿来尾插在哨兵位后面,以此类推,是val的先记录下一个节点的地址,再释放该节点;具体代码如下:
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* newhead = head;//创建临时变量,用来遍历链表
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));//加上哨兵位;
if (guard == NULL)//判断是否开辟空间成功;
{
perror("malloc");
exit(-1);
}
guard->next = NULL;
struct ListNode* ptali = guard;创临时节点,向后走;
if (head == NULL)//如果是空链表,直接返回NULL;
{
return NULL;
}
while (newhead != NULL)//遍历链表;
{
if (newhead->val!= val)//不是val,把链表的节点赋给带哨兵位的新的链表
{
ptali->next = newhead;
ptali = newhead;//新链表往后走;
newhead = newhead->next;//原来的链表也往后走;
}
else//是val,保留原来链表节点的下一个节点,释放现在的节点,将下一个节点赋予newnode,实现向后走;
{
struct ListNode* next = newhead->next;
free(newhead);
newhead= next;
}
}
if (newhead== NULL)//当原来的链表遍历完;
{
ptali->next = NULL;//把新链表的尾节点的next置为空;
}
struct ListNode*newnode=guard->next;//创建临时节点,记录下要返回的节点;
free(guard);//释放开辟的哨兵位;
return newnode;返回新链表的头节点;
}
//////
2合并两个有序链表:
解题思路:创建一个哨兵位,依次比较尾插,具体代码如下:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
//创建一个哨兵位;
struct ListNode*phead=(struct ListNode*)malloc(sizeof(struct ListNode));
phead->next=NULL;
struct ListNode*head=phead;//创建临时节点,方便遍历数组;
if(list1==NULL&&list2==NULL)//如果两个链表都为空,直接返回NULL;
{
return NULL;
}
while(list1!=NULL&&list2!=NULL)//如果都不为NULL,开始遍历比较;
{
if(list1->val<=list2->val)
{
head->next=list1;
head=head->next;
list1=list1->next;
}
else
{
head->next=list2;
head=head->next;
list2=list2->next;
}
}
//如果出现上面的遍历结束后,还有一个链表还有元素,那么不用再比较,直接尾插
while(list1!=NULL)//如果第一个链表还有元素;
{
head->next=list1;
head=head->next;
list1=list1->next;
}
while(list2!=NULL)//如果第二个链表还有元素;
{
head->next=list2;
head=head->next;
list2=list2->next;
}
struct ListNode*pphead=phead->next;//创建临时节点,记录要返回的头节点;
free(phead);//释放哨兵位;
return pphead;//返回头节点;
}
//////
3反转链表:
解题思路:创建一个空指针的节点,然后遍历原链表依次头插;具体代码如下:
struct ListNode* reverseList(struct ListNode* head)
{
if(head==NULL)//如果原链表为空,直接返回空;
{
return NULL;
}
struct ListNode*phead=NULL;//创建临时空节点,
while(head!=NULL)//遍历原链表,头插;
{
struct ListNode*next=head->next;//先把原链表节点的下一个节点记录下来;
head->next=phead;//头插;
phead=head;//让之前的后一个节点成为头节点;
head=next;//将记录下的下一个节点赋给原链表节点,实现遍历;
}
return phead;//返回反转后的头结点
}
///
///
4链表的中间节点:
解题思路:利用快慢指针slow,fast,当快指针fast走到尾节点或者NULL,慢指针slow就在中间节点;具体代码如下:
struct ListNode* middleNode(struct ListNode* head)
{
//创建快慢指针,一开始都在头节点;
struct ListNode*slow=head;//慢指针;
struct ListNode*fast=head;//快指针;
while(fast!=NULL&&fast->next!=NULL)//如果是偶数个元素,走到尾节点为NULL就结束,如果是奇数个元素,走到尾节点下一个节点NULL结束;
{
slow=slow->next;//慢指针一次走一步;
fast=fast->next->next;//快指针一次走慢指针的两倍步长;
}
return slow;//返回慢指针,慢指针所指向的节点就是中间节点;
}
//////
5链表中倒数第k个节点:
解题思路:创建快慢指针,让快指针走差异步(k步),然后再一起走,当快指针走到尾节点时,慢指针就是链表中倒数第k个节点;具体代码如下:
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k )
{
//创建快慢指针;
struct ListNode*slow=pListHead;//慢指针;
struct ListNode*fast=pListHead;//快指针;
if(pListHead==NULL)//如果链表为空,直接返回NULL;
{
return NULL;
}
while(k--)//先让快指针走差异步;
{
if(fast==NULL)//如果k大于链表节点的个数,直接返回NULL;
{
return NULL;
}
fast=fast->next;
}
while(fast!=NULL)//遍历链表;
{
slow=slow->next;
fast=fast->next;
}
return slow;//返回慢指针,此时慢指针就是倒数第k个节点;
//////
1链表分割:
解题思路:创建两个哨兵位,一个存大于x的节点,一个存小于x的节点,最后,将两个带哨兵位的新链表链接在一起,释放掉哨兵位;具体代码如下:
class Partition {
public:
ListNode * partition(ListNode * pHead, int x)
{
//创建两个哨兵位;
ListNode*pheadA = (ListNode*)malloc(sizeof(ListNode));
ListNode*pheadB = (ListNode*)malloc(sizeof(ListNode));
//再创建两个临时节点,方便向后链接;
ListNode*ptali = pheadA;
ListNode*plist = pheadB;
ListNode*cur = pHead;//创建临时节点,遍历链表;
ptali->next= NULL;
plist->next =NULL;
while (cur != NULL)
{
if (cur->val < x)//小于x的存在pheadA链表中;
{
ptali->next = cur;
ptali = ptali->next;
}
else大于x的存在pheadB链表中;
{
plist->next = cur;
plist = plist->next;
}
cur = cur->next;//向后遍历;
}
ptali->next = pheadB->next;//创建临时变量,把大于x的链表的头节点记录下来;
plist->next = NULL;//将小于x的链表尾节点置为NULL,防止指向之前的节点形成闭环;
pHead = pheadA->next;
//释放哨兵位
free(pheadA);
free(pheadB);
return pHead;
}
};
//////
2链表的回文结构:
解题思路:先用快慢指针找到中间节点,然后反转链表,最后遍历比较反转后的后半边链表和整个链表;具体代码如下:
struct ListNode* middleNode(struct ListNode* head){
struct ListNode*slow = head;
struct ListNode*fast = head;
while(fast!=NULL && fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
struct ListNode*swaprome(struct ListNode* head)
{
struct ListNode*cur=head;
struct ListNode*pphead=NULL;
while(cur!=NULL)
{
struct ListNode*next=cur->next;
cur->next=pphead;
pphead=cur;
cur=next;
}
return pphead;
}
class PalindromeList {
public:
bool chkPalindrome(ListNode* A)
{
struct ListNode*phead=middleNode(A);//调用寻找中间节点的函数;
struct ListNode*ptali=swaprome(phead);//调用反转链表的函数;
while((A!=NULL)&&(ptali!=NULL))//比较反转后的半边链表和整个链表;
{
if(A->val!=ptali->val)
{
return false;//如果有不同,直接返回false;
}
//实现向后遍历
A=A->next;
ptali=ptali->next;
}
return true;//如果反转后的半边链表遍历完没有不同的,说明此链表为回文结构,返回true;
}
};