单链表的k逆序

【题目】

有一个单链表,请设计一个算法,使得每K个节点之间逆序,如果最后不够K个节点一组,则不调整最后几个节点。例如链表1->2->3->4->5->6->7->8->null,K=3这个例子。调整后为,3->2->1->6->5->4->7->8->null。因为K==3,所以每三个节点之间逆序,但其中的7,8不调整,因为只有两个节点不够一组。
给定一个单链表的头指针head,同时给定K值,返回逆序后的链表的头指针。


方法一:不使用额外空间,纯手动,时间复杂度O(N)

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class KInverse {
public:
    ListNode* inverse(ListNode* head, int K) {
        if(head != NULL && head->next != NULL&& K > 1){
            ListNode* cur = head;
            ListNode* pre = NULL;
            ListNode* next = NULL;
            ListNode* start = NULL;
            int counter = 1;   //计数器初值为1,计到k
            while(cur != NULL){ //只判断是否为空程序结束,通过k来判断是否需要逆序
                next = cur->next;
                if(counter == K){   //满足k个,逆序它
                    start = pre == NULL ? head : pre->next;//第一组的第k个作为链表头部
                    head = pre == NULL ? cur : head;
                    reverse_local(pre, start, cur, next); 
                    pre = start; //pre是用来每次保存上一组k个结点尾节点的
                    counter = 0;  //计数器为0,因为接下来会++
                }
                ++counter;
                cur = next;//千万注意是cur=next,而不是cur=cur->next因为cur->next指向被逆序改变了
            }
        }
        return head;
    }
private:
    void reverse_local(ListNode* left, ListNode* start, ListNode* end, ListNode* right){
        ListNode* behind = start;
        ListNode* current = start->next;;
        ListNode* front = current->next;
        while(current != right){
            front = current->next;
            current->next = behind;
            behind = current;
            current = front;
        }
        if(left != NULL)//如果是第一组,不必更新,因为pre是用来替除了第一组保存前一组尾节点的
            left->next = end; //由之前的pre->next=right改为pre->next=end
        start->next = right;//start实际上先连接
    }
};

方法一注意的点都在注释中了,下面给出它的图解:


这种方法超级考验代码实现能力,很容易漏掉情况,我觉得谁要是没练过这类题,面试中基本不可能在有限时间做出来。


方法二:使用栈,时间复杂度为O(2N),空间复杂度O(N)。比较容易,直接利用栈将链表从每K个节点倒序赋值给从1开始的节点。

有一种做法是使用栈但是修改指针,但是那样太麻烦了,时间复杂度是相同的。所以直接赋值即可。

class KInverse {
public:
    ListNode* inverse(ListNode* head, int k) {
        if(head != NULL && head->next != NULL && k > 1){
        	ListNode* wait = head;
            ListNode* act = head;
            stack<int> st;
            int counter = 1; 
            while(act != NULL){   //此类问题使用NULL控制循环,使用循环外变量counter控制是否逆序
 				st.push(act->val);
                if(counter == k){
                	while(!st.empty()){
                    	wait->val = st.top();
                    	st.pop();
                    	wait = wait->next;
                    }
                    counter = 0;
                }
                ++counter;
            	act = act->next;
            }
        }
        return head;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值