力扣、牛客网->链表相关题目(篇一)(c语言)

目录

1.LeetCode203.移除链表元素

方法一:双指针

方法二:创建新链表

方法三:递归

2.LeetCode206.反转链表

方法一:创建新链表

方法二:三指针

方法三:递归

3.LeetCode876.链表的中间节点

解法:快慢指针

4.牛客网JZ22:链表中倒数第k个结点

 解法:快慢指针

 5.LeetCode21.合并两个有序链表

方法一:创建新链表

方法二:递归


1.LeetCode203.移除链表元素

方法一:双指针

设两个指针prev和cur,让cur指向头,prev指向空,依次删除节点值为val的节点

    //方法一:双指针
    struct ListNode*cur=head,*prev=NULL;
    while(cur){
        if(cur->val==val){
            if(cur==head){
                head=cur->next;
                free(cur);
                cur=head;
            }else{
                 prev->next=cur->next;
             free(cur);
             cur=prev->next;
            }
            
        }else{
            prev=cur;
            cur=cur->next;
        }
    }
    return head;

方法二:创建新链表

遍历链表,让不是val值的节点尾插到新链表

//方法二:创建新链表
    struct ListNode*newhead=(struct ListNode*)malloc(sizeof(struct ListNode)); 
    newhead->next=NULL;
    struct ListNode*tail=newhead;
    struct ListNode*cur=head;
    while(cur){
        if(cur->val==val){
            struct ListNode*next=cur->next;
            free(cur);
            cur=next;
        }else{
          tail->next=cur;
          tail=tail->next;
          cur=cur->next;
        }
    }
    tail->next=NULL;
    return newhead->next;

方法三:递归

1.判断头结点,若满足条件则删除

2.将头结点后视为一个链表2

3.递归删除链表2(递归1-3步)

4.返回头结点

//方法三:递归
    if(head==NULL)return NULL;
    while(head&&head->val==val){
        struct ListNode*next=head->next;
        free(head);
        head=next;
    }
    if(head)head->next=removeElements(head->next,val);
    return head;

2.LeetCode206.反转链表

方法一:创建新链表

创建一个指针变量newlist让它指向头指针head,创建指针cur指向头结点的下一个结点,让头指针指向NULL,用next指针指向cur结点的下一个结点。如图:

由图将右链表依次头插到左链表即可 ,最后返回*newlist或head即可。

//方法一:创建新链表
   if(head==NULL)return NULL;
   struct ListNode**newlist=&head;
   struct ListNode*cur=head->next; 
     head->next=NULL;
   while(cur){
       struct ListNode*next=cur->next;
       cur->next=(*newlist); 
       *newlist=cur;
       cur=next;
   }

   return (*newlist);

方法二:三指针

创建三个分别指向当前结点、前驱结点、和下一个结点的指针变量,前驱结点开始时指向头结点,让当前结点指向前驱结点,然后让三个指针往后走,直到当前结点指向空。

//方法三 三指针
struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL||head->next==NULL)return head;
    struct ListNode*pre=NULL,*cur=head,*next=head->next;
    while(cur){
        cur->next=pre;
        pre=cur;
        cur=next;
        if(next)
        next=next->next;
    }
return pre;
}

方法三:递归

1.让tail指针指向头结点的下一个结点。p为以tail下一个结点开始的链表反转后的头结点的地址,也是链表反转后的地址。

2.让head指针指向空节点

3.让tail指向头结点

4.返回p

//2.递归实现
if(head==NULL||head->next==NULL)return head;
struct ListNode*tail=head->next,*p=reverseList(tail);
head->next=NULL;
tail->next=head;
return p;

3.LeetCode876.链表的中间节点

解法:快慢指针

快指针走两步,慢指针走一步,快指针走完,慢指针就指向中间节点了。

struct ListNode* middleNode(struct ListNode* head){
if(head==NULL||head->next==NULL)return head;
struct ListNode*fast=head,*slow=head;
while(fast!=NULL&&fast->next!=NULL){
    fast=fast->next->next;
    slow=slow->next;
}
return slow;
}

4.牛客网JZ22:链表中倒数第k个结点

 解法:快慢指针

让快指针先走k步,然后两指针再一起走,快指针走完,慢指针就指向链表中倒数第k个节点。

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    if(pListHead==NULL||pListHead->next==NULL)return pListHead;
    struct ListNode*fast=pListHead,*slow=pListHead;
    while(k--){
     if(fast==NULL)return NULL;
        fast=fast->next;
    }
    while(fast){
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

 5.LeetCode21.合并两个有序链表

 

方法一:创建新链表

让cur1,cur2指针分别指向两个链表的头结点,将cur结点的值小的节点尾插到新链表上,并让cur指针往后走,直到有一个cur指针指向空为止。

//方法一:创建新链表
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
if(list1==NULL||list2==NULL)return list1==NULL?list2:list1;
    struct ListNode*cur1=list1,*cur2=list2;
    struct ListNode*newlist;
    if(cur1->val<cur2->val){
        newlist=cur1;
        cur1=cur1->next;
    }
    else{
     newlist=cur2;
    cur2=cur2->next;    
    }
    struct ListNode*tail=newlist;
    while(cur1&&cur2){
        if(cur1->val<cur2->val){
          tail->next=cur1;
          cur1=cur1->next;
          tail=tail->next;
        }else{
            tail->next=cur2;
            cur2=cur2->next;
            tail=tail->next;
        }
    }
   if(!cur1)
       tail->next=cur2;
   else
       tail->next=cur1;
    return newlist;
}

方法二:递归

1.判断list1和list2结点的值大小关系,若list1的值小,让list1节点为头结点。(若list2的值小则list2做头结点,以下步骤反之)

2.合并以list1->next和list2分别做头节点的两个链表(递归实现),返回合并后链表的头结点,让list1的下个节点为该节点。

3.返回list1作为头结点。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
   if(list1==NULL||list2==NULL)return list1==NULL?list2:list1;
   if(list1->val<list2->val){
       list1->next=mergeTwoLists(list1->next,list2);
       return list1;
   } 
   else {
       list2->next=mergeTwoLists(list1,list2->next);
       return list2;
   }
}

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值