单链表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 小时前
数据结构-链表【chapter1】【c语言版】
c语言·开发语言·数据结构·链表·visual studio
阿洵Rain2 小时前
【C++】哈希
数据结构·c++·算法·list·哈希算法
Leo.yuan2 小时前
39页PDF | 华为数据架构建设交流材料(限免下载)
数据结构·华为
忘梓.3 小时前
排序的秘密(1)——排序简介以及插入排序
数据结构·c++·算法·排序算法
y_m_h5 小时前
leetcode912.排序数组的题解
数据结构·算法
1 9 J6 小时前
数据结构 C/C++(实验三:队列)
c语言·数据结构·c++·算法
921正在学习编程6 小时前
数据结构之二叉树前序,中序,后序习题分析(递归图)
c语言·数据结构·算法·二叉树
毕竟秋山澪6 小时前
岛屿数量 广搜版BFS C#
数据结构·算法·宽度优先
乔冠宇7 小时前
环状 DNA 序列的最小表示法
java·数据结构·算法