链表QJ 2(移除链表元素、反转链表、合并两个有序链表、链表分割、链表回文结构)

前言:

今天我们继续做链表算法题,相比于上次的QJ1,这次选的题更容易、基础一点。如有错误,请评论指出,制作不易,还望给个关注点赞哦!🤗🤗

下面是所讲算法题答题链接,大家可以先做一下,再看我的解答🤓💡👆

1、移除链表元素

https://leetcode.cn/problems/remove-linked-list-elements/description/

2、反转链表

https://leetcode.cn/problems/reverse-linked-list/description/

3、链表的中间结点

https://leetcode.cn/problems/middle-of-the-linked-list/description/

4、合并两个有序链表

https://leetcode.cn/problems/merge-two-sorted-lists/description/

5、链表分割
https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70
6、链表的回文结构
https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa

一、移除链表元素

1、答案
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
    //创建新链表
    ListNode* newHead,*newTail;
    newHead=newTail=NULL;
    //遍历原链表
    ListNode* pcur=head;
    while(pcur)
    {
        if(pcur->val!=val)
        {
            if(newHead==NULL)
            {
                newHead=newTail=pcur;
            }
            else
            {
                //链表不为空
                newTail->next=pcur;
                newTail=newTail->next;
            }
            
        }
        pcur=pcur->next;
    }
    if(newTail)
    {
        newTail->next=NULL;
        
    }
    return newHead;
}
2、解析

这个题的解决方法是创建一个新链表,在遍历原链表,找到值不为val的节点,并把该节点往新链表中进行尾插。

二、反转链表

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

2、解析

思路一:将链表头插到新链表上。(链表的头插法)

思路二:创建三个指针,直接在原链表上修改指针的方向。(上述答案为该思路的答案)

三、求链表的中间结点

1、答案
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    ListNode *slow=head,*fast=head;
    //慢指针每次走一步,快指针每次走两步
    while(fast&&fast->next)//等价于(fast!=NULL&&fast->next!=NULL)
    {
       slow=slow->next;
       fast=fast->next->next;
    }
    return slow;
}
2、解析

思路一:第一次循环,求出链表的总长度,计算中间节点的位置。第二次循环,根据中间节点的位置求中间结点。

思路二:利用快慢指针(上一篇博客中讲过快慢指针,链表QJ1),快指针走两步,慢指针走两步。(上面的代码为该思路的答案)。

四、合并两个有序链表

1、答案
 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,*newTail;
        newHead=newTail=(ListNode*)malloc(sizeof(ListNode));
        ListNode* l1=list1;
        ListNode* l2=list2;
        while(l1 && l2)
        {
            if(l1->val < l2->val)
            {
            newTail->next=l1;
            newTail=newTail->next;
            l1=l1->next;
            }
            else
            {
                newTail->next=l2;
            newTail=newTail->next;
            l2=l2->next;
            }

        }
        if(l1)
         newTail->next=l1;
         if(l2)
         newTail->next=l2;
       ListNode* ret=newHead->next;
        free(newHead);
        newHead=NULL;
        return ret;
    }
2、解析

思路:创建新链表,遍历两个原链表,比较大小,谁小谁就尾插到新链表中。

注意在上面的代码中,为方便我们在创建新链表时使用动态申请新结点,令头节点不为空,最后应该释放动态申请的新结点。把结点的值给另一个新建节点,再释放头结点。

五、链表分割

1、答案
#include <cstddef>
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        //创建两个非空链表:小链表和大链表
        ListNode* lessHead,*lessTail;
        lessHead=lessTail=(ListNode*)malloc(sizeof(ListNode));
        ListNode* greaterHead,*greaterTail;
        greaterHead=greaterTail=(ListNode*)malloc(sizeof(ListNode));
        //遍历链表(小于x的尾插到小链表,大于x的尾插到大链表)
        ListNode*pcur=pHead;
        while(pcur)
        {
            if(pcur->val<x)
            {
                lessTail->next=pcur;
                lessTail=lessTail->next;
            }
            else 
            {
                greaterTail->next=pcur;
                greaterTail=greaterTail->next;
            }
            pcur=pcur->next;
        }
        //将大链表的尾结点的next指针置为NULL;
        greaterTail->next=NULL;
        //大小链表首尾相连
        lessTail->next=greaterHead->next;
        ListNode* ret=lessHead->next;
        free(lessHead);
        free(greaterHead);
        lessHead=greaterHead=NULL;
        return ret;

    }
};
2、解析

思路:创建两个新链表,小于x的值尾插到一个链表中,大于x的值尾插到一个链表中,最后小链表的尾链接大链表的头,注意最后将大链表的尾指针的next指针指向NULL,否则陷入死循环;

六、链表的回文结构

1、答案
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        int arr[900]={0};
        ListNode* pcur=A;
        int i=0;
        //遍历链表,将链表中每个结点中的数值保存在数值中
        while(pcur)
        {
            arr[i++]=pcur->val;
            pcur=pcur->next;
        }
        //i即节点的个数
        //找中间结点,判断是否为回文数字
        int left=0;
        int right=i-1;
        while(left<right)
        {
            if(arr[left]!=arr[right])
            {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};
2、解析

思路:创建新的数组,遍历原链表,将原链表的值放入数组,在数组中判断是否为回文结构;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值