单链表经典算法OJ题

文章目录

  • 经典算法OJ题类型
    • 1、移除链表元素
    • 2、反转链表
    • 3、合并两个有序链表
    • 4、链表的中间结点
    • 5、环形链表的约瑟夫问题
    • 6、分割链表

经典算法OJ题类型

1) 接口型
直接定义实现功能的函数,已经帮忙写好所需用到的库函数

2) IO型
相当于创建一个新项目,需要库函数,main函数的使用

1、移除链表元素

单链表相关经典算法OJ题1移除链表元素
.在这里插入图片描述

typedef struct ListNode SLNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
   SLNode* newHead;
   SLNode* newTail;
   newHead=NULL;
   newTail=NULL;
   SLNode* pcur=head;
   //开始遍历链表
   while(pcur){
       if(pcur->val!=val){
           //把当前节点插入到新的链表中
           //1、链表为空,插入进来的新的节点就是链表的头结点和尾节点
           if(newHead == NULL){
               newHead=newTail=pcur;
           }
           else{
               newTail->next=pcur;
               newTail=newTail->next;
           }
       }
       pcur=pcur->next;
   }
   if(newTail)
       newTail->next=NULL;
   return newHead;
}

2、反转链表

单链表相关经典算法OJ题2:反转链表

在这里插入图片描述

typedef struct ListNode SLNode;
struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL) {
        return NULL;
    }
    SLNode* p1 = NULL;
    SLNode* p2 = head;
    SLNode* p3 = p2->next;
    while (p2) {
        p1 = p2;
        if (p1 == head) {
            p1->next = NULL;
        }
        p2 = p3;
        if (p2 != NULL) {
            p3 = p3->next;
            p2->next = p1;
        }
    }
    return p1;
}

3、合并两个有序链表

单链表相关经典算法OJ题3:合并两个有序链表
在这里插入图片描述

typedef struct ListNode SLNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    SLNode* L1=list1;
    SLNode* L2=list2;
    SLNode* newHead=NULL;
    SLNode* newTail=NULL;
    if(L1 == NULL)
        return L2;
    if(L2 == NULL)
        return L1;
    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(L2){
            newTail->next=L2;
            newTail=newTail->next;
            L2=L2->next;
    }
    if(L1){
            newTail->next=L1;
            newTail=newTail->next;
            L1=L1->next;
    }

    return newHead;
}

4、链表的中间结点

单链表相关经典算法OJ题4:链表的中间结点
在这里插入图片描述

 typedef struct ListNode SLNode;
struct ListNode* middleNode(struct ListNode* head) {
    if(head==NULL || head->next==NULL){
        return head;
    }
    SLNode* slow=head;
    SLNode* fast=head;
    while(fast && fast->next){  //{fast->next && fast}在偶数的情况下,fast刚好走到NULL此时按照顺序进行判断,NULL->next,这样就会报错就像此地无银三百两
        slow=slow->next;        
        fast=fast->next->next;
    }
    return slow;
}

5、环形链表的约瑟夫问题

循环链表经典应用-环形链表的约瑟夫问题

输入: 5 , 2
返回值: 3
说明: 开始5个人 1,2,3,4,5 ,从1开始报数,1->1,2->2编号为2的人离开
1,3,4,5,从3开始报数,3->1,4->2编号为4的人离开
1,3,5,从5开始报数,5->1,1->2编号为1的人离开
3,5,从3开始报数,3->1,5->2编号为5的人离开
最后留下人的编号是3

typedef struct ListNode SLNode;

//对节点的创建
SLNode* ListBuyNode(int x){
    SLNode* node= (SLNode*)malloc(sizeof(SLNode));
    if(node == NULL){
        perror("malloc fail!");
        exit(1);
    }
    node->val=x;
    node->next=NULL;
    return node;
}

//循环链表头尾相连的创建
SLNode* CreateList(int n){
    SLNode* phead=ListBuyNode(1);
    SLNode* tail=phead;
    for(int i=2;i<=n;i++){
        SLNode* node=ListBuyNode(i);
        tail->next=node;
        tail=tail->next;
    }
    tail->next=phead;
    return tail;
}

int ysf(int n, int m ) {
    //创建循环链表
    SLNode* prev=CreateList(n);
    //进行约瑟夫游戏
    SLNode* cur=prev->next; //就是头结点
    int count =1;
    while(cur->next!=cur){
        if(count == m){
            prev->next=cur->next;
            free(cur);
            cur=prev->next;
            count=1;
        }
        else{
            prev=cur;
            cur=cur->next;
            count++;
        }
    }
    // 此时链表只有一个节点
    return cur->val;
}

6、分割链表

单链表相关经典算法OJ题5:分割链表
在这里插入图片描述

typedef struct ListNode SLNode;
struct ListNode* partition(struct ListNode* head, int x) {
    if (head == NULL)
        return head;
    //创建带头的大小链表
    SLNode* lesshead, * lesstail;
    SLNode* greaterhead, * greatertail;
    //大小链表的哨兵位
    lesshead = lesstail = (SLNode*)malloc(sizeof(SLNode));
    greaterhead = greatertail = (SLNode*)malloc(sizeof(SLNode));

    SLNode* cur = head;
    while (cur) {
        if (cur->val < x) {
            lesstail->next = cur;
            lesstail = lesstail->next;
        }
        else {
            greatertail->next = cur;
            greatertail = greatertail->next;
        }
        cur = cur->next;
    }
    // 将小链表的尾节点和大链表的头结点链接起来 
    if (greatertail)
        greatertail->next = NULL;
    lesstail->next = greaterhead->next;
    //需要把申请开辟的空间释放
    free(greaterhead);//大链表的哨兵释放
    SLNode* rethead = lesshead->next;
    free(lesshead);
    return rethead;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值