单链表OJ

1.删除链表中等于给定值 val 的所有节点

原题:. - 力扣(LeetCode)

思路:创建一个新的头结点和尾结点,创建一个pcur指向原链表的头结点进行遍历,当pcur->val不等于val的时候就让该结点尾插到新链表处;补充一点:创建新链表的时候如果链表为空则让新插入的结点称为头结点,这样子又要多一些判断,所以我们可以创建一个哨兵位,这样就保证新链表不为空且不需要判断;如下图和代码所示:

 typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    ListNode* pcur = head;
    ListNode* Newhead = (ListNode*)malloc(sizeof(ListNode));
    ListNode* Newtail = Newhead;
    while(pcur)
    {
        if(pcur->val!=val)
        {
            Newtail->next = pcur;
            Newtail = Newtail->next;
        }
        pcur = pcur->next;
    }
    if(Newtail)
    {
        Newtail->next = NULL;
    }
    ListNode* ret = Newhead->next;
    free(Newhead);
    return ret;
}

注意:在进行完while循环后,"5"就成了尾结点,那么还要让尾结点的next指针指向NULL,还要把Newhead释放掉,因为Newhead的空间是动态申请的防止内存泄漏;


2.反转一个单链表

原题:. - 力扣(LeetCode)

思路:创建三个指针n1指向NULL、n2指向头结点、n3指向头结点的下一个节点;然后让n2->next指向NULL,n1走到n2的位置,n2走到n3的位置,当n3不为NULL的时候n3走到n3->next的位置,最后再返回n1,这样一直循环到n2为NULL的时候;这个操作是让结点的指向改变,并没有改变结点的位置;代码如下:

 typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) 
{
    if(head==NULL)
    {
        return head;
    }
     ListNode* n1 = NULL;
    ListNode* n2 = head;
    ListNode* n3 = n2->next;
    while(n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3)
        {
        n3 = n3->next;
        }

    }
    return n1;
}

3.链表的中间结点

原题:. - 力扣(LeetCode)

思路:使用快慢指针,慢指针走一步,快指针走两步,后面要分两种情况,一种是结点总数为奇数的时候fast->next==NULL的时候停止,第二种是结点总数为偶数的时候则fast==NULL的时候停止,最后再返回慢指针;快慢指针原理:因为快指针每次都比慢指针快两步,所以假设快指针走了n步,那么慢指针就走了n/2步;代码如下:

 typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) 
{
    ListNode* Fastp;
    ListNode* Slowp;
    Fastp = Slowp = head;
    if(Fastp==NULL)
    {
        return Fastp;
    }
    while(Fastp&&Fastp->next)
    {
        Slowp = Slowp->next;
        Fastp = Fastp->next->next;
    }
    return Slowp;
}

4.合并两个有序链表

原题:. - 力扣(LeetCode)

思路:首先创建四个指针l1,l2,Newhead和Newtail,l1负责遍历第一个链表,l2负责遍历第二个链表,Newhead和Newtail负责新链表的头和尾;比较l1和l2,如果l1小于l2,那么就把l1放到新链表里面,如果l2小于l1就把l2放到新链表里面,合并两个链表中肯定有一个链表遍历不完,那么就把最后剩下的链表直接尾插到新链表即可,最后再返回新链表的头结点;如下代码所示:

 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
    if(list1==NULL)return list2;
    if(list2==NULL)return list1;
    //创建新链表
    ListNode* Newhead =NULL, *Newtail = NULL;
    ListNode* L1 = list1;
    ListNode* L2 = list2;
    while(L1&&L2)
    {
        if(L1->val <L2->val)
        {
            if(Newhead==NULL)
            {
                Newhead = Newtail = L1;
            }
            else
            {
                Newtail->next = L1;
                Newtail = Newtail->next;
            }
            L1 = L1->next;
        }
        else
        {
           if(Newhead==NULL)
            {
                Newhead = Newtail = L2;
            }
            else
            {
                Newtail->next = L2;
                Newtail = Newtail->next;
            }
            L2 = L2->next;
        }
    }
    if(L1)Newtail->next = L1;
    if(L2)Newtail ->next = L2;
    return Newhead;
}

END!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值