LeetCode 改变节点顺序相关题目

24Swap Nodes in Pairs

题意:交换两个相邻的节点,不够就不交换。

思路:设置一个pre节点,用来控制上一组节点和下一组节点的连接,维护后该节点就行,可以通过画图来思考。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode p(INT_MIN);
        ListNode* tmp1=&p,*tmp2;
        tmp1->next=head;
        head=tmp1;
        while(tmp1->next!=NULL && tmp1->next->next!=NULL)
        {
            tmp2=tmp1->next->next; //获得下一个节点
            tmp1->next->next=tmp2->next;
            tmp2->next=tmp1->next;
            tmp1->next=tmp2;
            tmp1=tmp2->next;
        }
        return head->next;
    }
};

25Reverse Nodes in k-Group

题意:转置k个节点,不够k个不转。

思路:因为是k个节点,k未知,所以要求出总共有多少个点,才能保证不会处理节点数不够k个的情况。第24题不用求总数是因为k已知。要控制维护第一个节点的前一个节点,节点顺序改变和上一题一样。

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode l(-1),*pre=&l,*cur=pre;
        pre->next=head;
        int num=0;
        while(cur=cur->next) num++;
        while(num>=k)
        {
            cur=pre->next;
            for(int i=1;i<k;i++)
            {
                ListNode* t=cur->next;
                cur->next=t->next;
                t->next=pre->next;//这里是pre->next,不能是cur,可自行验证。
                pre->next=t;
            }
            pre=cur;
            num-=k;
        }
        return l.next;
    }
};

147Insertion Sort List

题意:利用插入排序的思想来排序一个List。

思路:插入排序只在一个有序序列中插入一个数,插入后仍然有序。如果试图去遍历List来找最小值排序显然将花费大量时间且不是插入排序的思想。所以我们将一个List分为两部分,一部分为已排序的,一部分为未排序的,只要维护好已排序的,然后遍历未排序的插入就行。我们将第一个节点视为已排序好,直接从下一个节点开始与前一个节点进行判断,如果有序就寻找未排序节点的下一个节点,否则就遍历已排序节点来找到合适的位置插入。关键是程序的设计:虽然说分成两部分,但是没必要截断或者开辟新的空间,因为需要遍历两部分List,所以需要一个临时节点pos来遍历有序节点,未排序的节点用cur->next指向。

class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        if(!head||!head->next) return head;
        ListNode *l=new ListNode(0);
        l->next=head;
        ListNode *cur=head;
        while(cur->next)
        {
            ListNode *tmp=cur->next;
            if(tmp->val>=cur->val)
            {
                cur=cur->next;
                continue;
            }
            ListNode *pos=l;
            while(pos->next->val<tmp->val)
                pos=pos->next;
            cur->next=tmp->next;
            tmp->next=pos->next;
            pos->next=tmp;
        }
        return l->next;
    }
};

148Sort List

题意:在nlogn时间内和常量空间大小给一个链表排序。

思路:找到链表的middle节点,然后递归对前半部分和后半部分分别进行归并排序,最后对两个以排好序的链表进行Merge。

知识点1:归并排序的整体思想

知识点2:找到一个链表的中间节点的方法(用快慢指针实现)

知识点3:合并两个已排好序的链表为一个新的有序链表

class Solution {
public:
    ListNode* getMid(ListNode *head)
    {
        ListNode *slow=head,*quick=head;
        while(quick->next && quick->next->next)
        {
            quick=quick->next->next;
            slow=slow->next;
        }
        return slow;
    }
    
    ListNode* Merge(ListNode *a,ListNode*b)
    {
        ListNode l(0);
        ListNode *cur=&l;
        while(a && b)
        {
            if(a->val<b->val)
            {
                cur->next=a;
                a=a->next;
            }
            else
            {
                cur->next=b;
                b=b->next;
            }
            cur=cur->next;
        }
        cur->next=a?a:b;
        return l.next;
    }
    ListNode* sortList(ListNode* head) {
        if(!head||!head->next) return head;
        ListNode *mid=getMid(head);
        ListNode *next=mid->next;
        mid->next=NULL;
        return Merge(sortList(head),sortList(next));
    }
};

143Reorder List

题意:给出一个链表,改变链表的顺序,就是一个头后接一个尾,尾接原来头的下一个,以此类推。

思路:很容易想到按照题目的要求来,就是从第一个头节点直接指到最后一个节点。但是到了最后一个节点的时候就找不回前一个节点,或许遍历链表获取节点数,然后每次都从头开始遍历到需要的节点,明显时间会很长,而且链表已经改变,不能找到。所以采用分割列表和翻转链表的方法。对半分开,将后半段翻转,然后就是合并两个链表。

class Solution {
public:
    void reorderList(ListNode* head) {
        ListNode *slow=head,*quick=head;
        if(!head || !head->next|| !head->next->next) return ;
        while(quick->next &&quick->next->next)
        {
            slow=slow->next;
            quick=quick->next->next;
        }
        ListNode *mid=slow->next;
        slow->next=NULL;
        ListNode *last=mid;
        ListNode *pre=NULL;
        while(last)
        {
            ListNode *next=last->next;
            last->next=pre;
            pre=last;
            last=next;
        }
        while(head && pre)
        {
            ListNode *tmp=head->next;
            head->next=pre;
            pre=pre->next;
            head->next->next=tmp;
            head=tmp;
        }
    }
};







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值