单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构

目录

一、合并两个有序链表

二、链表分割

三、链表的回文结构


u解题的总体思路:

合并两个有序链表**:首先创建新链表的头节点哨兵位:本质上是占位子),为了减少一些判断情况,简化操作。然后我们再创建俩个指针分别指针两个单链表的头然后遍历比较,将两个指针指向节点的最小值接在新链表的后面。**

链表分割:创建两个新链表lessHead和greatHead**,一个存储原链表中小于x的节点,一个存储其他的节点,我们按顺序遍历原链表:当循环结束后,我们将存储小于x的节点的新链表lessHead接在另一个新链表greatHead的前面。**

链表的回文结构**:我们利用前面OJ题中的方法,找中间节点(快慢指针),反转链表(三指针法)解这道题,我们找到中间节点后,将中间节点后面的节点的指向反转,然后我们遍历这个反转后的链表与原链表比较****,看是否满足条件。**

一、合并两个有序链表

步骤1:

我们新建一个链表,初始化NewHead,NewTail三个指针都指向头节点NewList,然后,我们创建指针l1,l2分别指向list1和list2.

步骤2:当l1和l2指向的节点都不为NULL,循环遍历节点**,将最小值的节点接在新链表的后面,然后NewTail指向新链表的最后的节点位置上。**

步骤3:

我们将l1和l2指向链表节点不为NULL的接在NewTail的next域上,就完成了合并操作。

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    ListNode *l1 = list1,*l2 = list2;      
    ListNode *NewList = (ListNode*)malloc(sizeof(ListNode));    //创建头节点
    ListNode * NewHead, *NewTail; 
    NewHead = NewTail = NewList;    //初始化俩个指针都指向新链表
    //l1 和 l2 当前节点都不为NULL,遍历
    while(l1 && l2){
        if(l1->val < l2->val){
            NewTail->next = l1;
            l1 = l1->next;     //l1往后走
        }else{
            NewTail->next = l2;
            l2 = l2->next;     //l2往后走
        }
        NewTail = NewTail->next;     //更新NewTail 指向当前新插入的节点
    }
    //两者有一个为NULL(不可能同时为NULL)
    if(l1!=NULL){
        NewTail->next=l1;
    }else{
        NewTail->next=l2;
    }
    return NewList->next;
}

二、链表分割

步骤1:

**我们首先创建两个新的链表,lessHead存储节点值< x的节点,**greatHead存储节点值>= x的节点。

步骤2:

我们循环原链表,将每个节点按照判断接在各自的新链表中。

步骤3:

我们将lessHead的lessTail的next域接在greatHead的next前面,这样我们就实现了两个新链表的拼接.(注意:最后要将greatTail的next域置为NULL,防止死循环)

cpp 复制代码
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
#include <functional>
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        ListNode *pcur = pHead;
        //创建俩个头节点,分别存储小节点,和大节点
        ListNode *lessHead = (ListNode*)malloc(sizeof(ListNode));
        ListNode *lessTail = lessHead;
        ListNode *greatHead =  (ListNode*)malloc(sizeof(ListNode));
        ListNode *greatTail = greatHead;
        //循环遍历原链表中的每个节点
        while(pcur){
            if(pcur->val < x){
                lessTail->next = pcur;
                lessTail = lessTail->next;     //尾指针后移当新插入的节点 
            }else{
                greatTail->next = pcur;
                greatTail = greatTail->next;    //尾节点后移到新插入的节点
            }
            pcur = pcur->next;
        }
        //拼接两个新链表,将lessHead接入到greatHead后面
        lessTail->next = greatHead->next;
        greatTail->next = NULL;     //将最后的节点next域置为NULL
        return lessHead->next;
    }
};

三、链表的回文结构

步骤1:

我们首先写出找中间节点的函数middleNode,和反转链表的函数reverseList找到中间节点,然后,将中间节点后面的链表反转。(这两个函数在上个文章中详细讲解过,这里不再重点讲述

步骤2:

反转以mid为头节点的链表。

从这里可以看出我们的链表变成了俩个部分,然后我们遍历这两个链表比较各自节点的值是否相等相等说明我们原链表就是回文链表

cpp 复制代码
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    //反转链表
    ListNode* reverseList(ListNode* head){
        ListNode*n1,*n2,*n3;
        n1 = NULL;
        n2 = head;
        if(n2==NULL){
            return NULL;
        }
        n3 = n2->next;
        while(n2){
            n2->next = n1;
            n1 = n2;
            n2 = n3;
            if(n3)
                n3 = n3->next;
        }
        return n1;
    }
    //找中间节点
    ListNode* middleNode(ListNode* head){
        if(head==NULL){
            return NULL;
        }
        ListNode *slow,*fast;
        slow = fast = head;
        while(fast && fast->next){
            slow = slow->next;    //slow走一步
            fast = fast->next->next;    //fast走两步
        }
        return slow;
    }
    bool chkPalindrome(ListNode* A) {
        ListNode*phead = A;
        ListNode*mid = middleNode(A);    //找中间节点
        ListNode*pcur = reverseList(mid);   //反转以中间节点为头的后面的节点
        while(pcur){
            if(pcur->val != phead->val){
                return false;
            }
            pcur = pcur->next;
            phead = phead->next;
        }
        //循环正常结束,返回true
        return true;
    }
};
相关推荐
先鱼鲨生2 小时前
数据结构——栈、队列
数据结构
一念之坤2 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
IT 青年2 小时前
数据结构 (1)基本概念和术语
数据结构·算法
熬夜学编程的小王2 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
liujjjiyun3 小时前
小R的随机播放顺序
数据结构·c++·算法
Reese_Cool4 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法
djk88885 小时前
.net将List<实体1>的数据转到List<实体2>
数据结构·list·.net
搬砖的小码农_Sky5 小时前
C语言:结构体
c语言·数据结构
_OLi_7 小时前
力扣 LeetCode 106. 从中序与后序遍历序列构造二叉树(Day9:二叉树)
数据结构·算法·leetcode
我明天再来学Web渗透8 小时前
【SQL50】day 2
开发语言·数据结构·leetcode·面试