单链表题-ysf-反转-中间节点-回文-合并-分割

环形链表的约瑟夫问题_牛客题霸_牛客网

经典的约瑟夫环

 #include <stdint.h>
#include <stdlib.h>
//创建链表
typedef struct ListNode ListNode;
 ListNode* buyNode(int x){
    ListNode* newNode=(ListNode*)malloc(sizeof(ListNode));
    if(newNode==NULL){
        exit(1);
    }
    newNode->val=x;
    newNode->next=NULL;
    return newNode;
 } 
 //创建新节点
ListNode* createList(int n){
    ListNode* phead=buyNode(1);
    ListNode* ptail=phead;
    for(int i=2;i<=n;i++)
    {
        ptail->next=buyNode(i);
        ptail=ptail->next;
    }
    ptail->next=phead;
    return ptail;//返回ptail,因为需要有前一个指针和后一个指针

}

int ysf(int n, int m ) {
    // write code here
    ListNode* prev=createList(n);
    ListNode* pcur=prev->next;
    int count=1;
    while(pcur->next!=pcur){
        if(count==m){
            prev->next=pcur->next;//先让prev指向pcur的next要不然会找不到pcur
            free(pcur);
            pcur=prev->next;
            count=1;//置为1重新计数
        }
        else{
            prev=pcur;
            pcur=pcur->next;
            count++;
            
        }
    }
    return pcur->val;


}

. - 力扣(LeetCode)

反转链表

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

while(n2)
{
    n2->next=n1;
    n1=n2;
    n2=n3;
    if(n3)
    
    n3=n3->next;

}
return n1;
}

. - 力扣(LeetCode)

链表的中间节点 

struct ListNode* middleNode(struct ListNode* head) {
    struct ListNode*slow,*fast;;
    slow=fast=head;
    while(fast && fast->next)//不能写成while(fast->next && fast)
因为while会先判断前面的条件,而fast很可能直接就跑到空了,根本没有next属性导致报错
也就是短路性质
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}



. - 力扣(LeetCode)

回文链表

核心思想:将链表反转后,比较后半部分是否相同

遍历链表找到中间节点,从中间节点为分割线去比较两边是否先相同

typedef struct ListNode ListNode;
ListNode* reverseList(ListNode* head){
    ListNode* n1=NULL;
    ListNode* n2=head;
    ListNode* n3=head->next;
    while(n2){
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3){
            n3=n3->next;
        }
    }
    return n1;
}
bool isPalindrome(struct ListNode* head){
    if(head==NULL||head->next==NULL)
    {
        return true;
    }
    ListNode* fast=head;
    ListNode* slow=head;
    //遍历得到中间节点
    while(fast->next&&fast->next->next){
        slow=slow->next;
        fast=fast->next->next;
    }
    //右半部分反转后与前半部分比较
    ListNode* right=reverseList(slow->next);
    ListNode* cur=head;
    while(right){
        if(right->val!=cur->val){
            return false;
        }
        else{
            right=right->next;
            cur=cur->next;
        }
    }
    return true;
}

. - 力扣(LeetCode)

合并两个有序链表

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
   if(list1==NULL)//如果list1为空,返回list2
   {
    return list2;
   }
    if(list2==NULL)
   {
    return list1;
   }
    ListNode*head,*tail;
    head=tail=(ListNode*)malloc(sizeof(ListNode));
   while(list1&&list2)//判断循环条件,有一个为空就跳出循环
   {
    if(list1->val<list2->val)//l1<l2的值
    {
       tail->next=list1;//把list1链接到tail后面
            tail=tail->next;//tail迭代往后走
        list1=list1->next;//list1迭代往后走
    }
    else{
       tail->next=list2;
        tail=tail->next;
        list2=list2->next;
    }
   }
    if(list1)
    {
        tail->next=list1;
    }
    if(list2)
    {
        tail->next=list2;
    }
    ListNode* ret=head->next;
    free(head);
    head=NULL;//动态申请的空间需要手动释放
    return ret;
}
    

. - 力扣(LeetCode)

分割链表

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你不需要 保留 每个分区中各节点的初始相对位置。

思路:创建两个新链表,一个放比特定值小的数,一个放大的然后链接起来;

注意事项:对于大链表中的尾节点,需要置空,要不会出现死循环;创建哨兵位,需要手动释放空间;让小链表的尾指向大链表哨兵位的next

struct ListNode* partition(struct ListNode* head, int x){
struct ListNode*lesshead,*lesstail,*greaterhead,*greatertail;
//开两个哨兵位,虚拟节点,方便尾插
lesshead=lesstail=(struct ListNode*)malloc(sizeof(struct ListNode));
lesstail->next=NULL;
greaterhead=greatertail=(struct ListNode*)malloc(sizeof(struct ListNode));
greatertail->next=NULL;
struct ListNode*cur=head;
while(cur)
{
    if(cur->val<x)
    {
        lesstail->next=cur;
        lesstail=cur;
    }
    else
    {
        greatertail->next=cur;
        greatertail=cur;
    }
    cur=cur->next;
}
lesstail->next=greaterhead->next;
greatertail->next=NULL;
struct ListNode* newhead=lesshead->next;
free(lesshead);
free(greaterhead);
return newhead;
}

  • 32
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 25
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值