20200723

143.重排链表

1.先用快慢指针找到链表中点,把后半部分链表反转,再合并两部分链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* reverselist(struct ListNode* p)
{
    //反转链表
    struct ListNode* temp=NULL;
    struct ListNode* cur=NULL;
    while(p){
        temp=p->next;
        p->next=cur;
        cur=p;
        p=temp;
    }
    return cur;

}

void reorderList(struct ListNode* head){
    //用快慢指针把链表拆分成两部分,反转后一个链表,合并链表
    struct ListNode* fast=head; // 到链表末尾去
    struct ListNode* slow=head;
    struct ListNode* p=head;

    while(fast && fast->next && fast->next->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    //反转链表
    struct ListNode* revslow=reverselist(slow);
    struct ListNode* tmp1=NULL;
    struct ListNode* tmp2=NULL;
    //合并链表
    while(p && revslow){
        tmp1=p->next;
        tmp2=revslow->next;

        p->next=revslow;
        p=tmp1;
        revslow->next=p; 
        revslow=tmp2;  
    }

}

2.递归

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* HeadTail(struct ListNode* head, int len)
{
    if(len==1){
        struct ListNode* outtail=head->next;
        head->next=NULL;
        return outtail;
    }
    if(len==2){
        struct ListNode* outtail=head->next->next;
        head->next->next=NULL;
        return outtail;
    }
    //递归,找到中间链表的下一个节点,外层链表的尾巴
    struct ListNode* tail=HeadTail(head->next,len-2);
    //中间链表的头节点
    struct ListNode* subhead=head->next;
    head->next=tail;
    //外层的链表的尾巴
    struct ListNode* outtail=tail->next;
    tail->next=subhead;
    return outtail;
}

void reorderList(struct ListNode* head){
    //递归
    if(head==NULL || head->next==NULL || head->next->next==NULL) return head;
    struct ListNode* p=head;
    int len=0;
    while(p){
        p=p->next;
        len++;
    }
    HeadTail(head,len);
}

21.合并两个有序链表

1.依次比较两个链表的每个值,链接到新的链表上。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    int val1=0;
    int val2=0;
    struct ListNode* newlist=(struct ListNode*)malloc(sizeof(struct ListNode));
    newlist->next=NULL;
    struct ListNode* newhead=newlist;

    while(l1 && l2)
    {
        val1=l1->val;
        val2=l2->val;
        if(val1<=val2){
            newlist->next=l1;
            l1=l1->next;
        }
        else{
            newlist->next=l2;
            l2=l2->next;
        }
        newlist=newlist->next;
    }
    if(l1){
        newlist->next=l1;
    }
    if(l2){
        newlist->next=l2;
    }
    return newhead->next;
}

2.递归
如果l1的当前值小于l2的当前值,l1->next就等于递归地合并l1->next和l2,另一种情况同理

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(l1==NULL || l2==NULL){
        return l1 ? l1 : (l2 ? l2 : NULL);
    }
    if(l1->val <= l2->val){
        l1->next=mergeTwoLists(l1->next,l2);
        return l1;
    }
    else{
        l2->next=mergeTwoLists(l1,l2->next);
        return l2;
    }
    
}

160.相交链表

1.两个指针

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    //两个指针分别从A和B的头出发,
    //走完自己的一条链表后走另外一条,
    //如果相交的话会在交点处相遇
    if(headA==NULL || headB==NULL) return NULL;
    struct ListNode* p=headA;
    struct ListNode* q=headB;

    while(p || q){
        if(p==q){
            return p;
        }
        p=p->next;
        q=q->next;
        if(p==NULL && q==NULL){
            return NULL;
        }
        if(p==NULL){
            p=headB;
        }
        if(q==NULL){
            q=headA;
        }
    }
    return NULL;
}

有点慢

1290.二进制链表转整数

先求出链表的长度,然后从头开始,计算对应的十进制数。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


int getDecimalValue(struct ListNode* head){
    int len=0;
    struct ListNode* p=head;
    struct ListNode* q=head;
    int num=0;
    while(p){
        p=p->next;
        len++;
    }
    while(q){
        num+= (q->val)*pow(2,len-1);
        q=q->next;
        len--;
    }
    return num;
}

92.反转链表2

1.常规的反转链表,连接各个部分

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* reverseBetween(struct ListNode* head, int m, int n){
    // 找出前一个反转链表的前一个节点和后一个节点,反转的单独反转,再连起来
    if(head==NULL) return head;
    if(m==n) return head;
    struct ListNode* dummy=NULL;
    struct ListNode* q=head;
    //找到开始反转的节点q和它的前一个节点dummy
    while(m>1){
        dummy=q;
        q=q->next;
        m--;
        n--;
    }
    struct ListNode* revtail=q; //反转后的尾部节点
    //反转链表 
    struct ListNode* temp=NULL,*cur=dummy,*p=revtail;
    while(n){
        temp=p->next;
        p->next=cur;
        cur=p;
        p=temp;
        n--;//这样写才可以,如果写成length的话是错的
    }
    // 反转后,cur是null(如果从第一个开始反转)或反转的第一个结点
    if(dummy){
        dummy->next=cur;
    }
    else{
        head=cur;
    }
    revtail->next=p;
    return head;
}

2.递归

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* nextnode=NULL;//反转链表的下一个节点
struct ListNode* reverseN(struct ListNode* head, int n){
    //反转前n个链表节点
    if(n==1){
        nextnode=head->next;
        return head;
    }
    struct ListNode* last=reverseN(head->next,n-1);
    head->next->next=head;
    head->next=nextnode;
    return last;//这里怎么返回的last??
}
struct ListNode* reverseBetween(struct ListNode* head, int m, int n){
    // 递归
    if(m==1){
        return reverseN(head,n);
    }
    head->next=reverseBetween(head->next,m-1,n-1);
    
    return head;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值