K 个一组翻转链表的实现

原理:从头开始,每数够K个数就将其翻转,不够不反转

#include<stdio.h>
#include <stdlib.h>

struct ListNode {
     int val;
     struct ListNode *next;
};
//反转函数
//pre:反转之前的一个节点,end:第k组反转之前的指针
struct ListNode* reverse(struct ListNode* pre, struct ListNode* end,struct ListNode* next){
        struct ListNode* start = pre->next; //第k组开始反转的指针
        struct ListNode* last;  //下一个节点
         struct ListNode* startTemp = start;  //第K组开始节点的备份
        while(start != end){          
                last = start ->next;
                start ->next = next;
                next = start;               
                start = last;
        }

        //将源第K组end节点接到第K-1组后边
        end ->next = next;
        pre ->next = end;
        //现在需要将pre定位到原来的end,也就是原来的start
        return startTemp;
}
//数够k个就反转
struct ListNode* reverseKGroup(struct ListNode* head, int k){
        //标记次数,遇到k就重置为0;
        int  number = 0;
 
        //生成一个虚拟头指针
        struct ListNode newhead;  //虚拟头节点的结构体
        struct ListNode* virtualhead01 = &newhead,*virtualhead = &newhead;  //virtualhead01虚拟头节点的复制,作为返回值使用
        
        struct ListNode *pre;    //上一个节点保存

        newhead.next = head;    
        if(head == NULL || head ->next ==NULL){
                return head;
        }
        while(head != NULL){
                number++;
                pre = head;
                head = head ->next;
                
                //数够k个节点,翻转
                if(number == k){
                       virtualhead = reverse(virtualhead,pre,head);
                        number=0;
                }

        }
        return virtualhead01->next;
}
struct ListNode* init(struct ListNode** head,int *w,int size){
	int i = 1; 
	struct ListNode *temp01, *temp;;
	(*head) =(struct ListNode*)malloc(sizeof(struct ListNode));
	(*head)->val = w[0];
	(*head)->next = NULL;
	temp01 = *head;
	for(i =1; i< size; i++){
		temp=(struct ListNode*)malloc(sizeof(struct ListNode));
		temp->val = w[i];
		temp->next = NULL;
		temp01->next = temp;
		temp01 = temp;	

	}
	
	return *head;
}

void print(struct ListNode* head){
	while(head != NULL){
		printf("%d ", head->val);
		head = head ->next;
	}
	printf("\n");
}

int main(){
	struct ListNode* head;
	int w[5] = {1,2,3,4,5};
	int k= 2;
        head = init(&head,w,5);
	
	head = reverseKGroup(head,k);
	print(head);

	return 0;

}

原理:

d1cd03544be129d7d54cda72f2fb0f60ce2.jpg

方法二:

//数够k个就反转
struct ListNode* reverseKGroup(struct ListNode* head, int k){
        //标记次数,遇到k就重置为0;
        int  number = 0;
 
        //生成一个虚拟头指针
        struct ListNode newhead;  //虚拟头节点的结构体
        struct ListNode *pre = &newhead;
        struct ListNode *end = &newhead;  //virtualhead01虚拟头节点的复制,作为返回值使用
        newhead.next = head;   //无论怎么变化,newhead.next 一定是新头节点

        while(end->next != NULL){
                for(number =0; number< k && end != NULL) end = end->next;
                if(end == NULL) break;
                struct ListNode *start = pre ->next;
                struct ListNode *next  = end ->next;
                end ->next = NULL;             
                //数够k个节点,翻转
                pre->next = reverse(start);
                start->next = next;
                pre = start;
                end = pre;
        }
        return newhead.next;
}

第三种方法:栈,每次取栈顶元素,实现翻转

struct ListNode* reverseKGroup(struct ListNode* head, int k){
        //创建栈
        struct ListNode* queen[3];
        int rear = -1;
        //生成一个虚拟头指针
        struct ListNode newhead;  //虚拟头节点的结构体
        struct ListNode *pre = &newhead;
        struct ListNode *temp= head;  //第一个节点的复制

        newhead.next = head;   //无论怎么变化,newhead.next 一定是新头节点
        while(true){
                int count =0;
                while(temp != NULL && count <k){
                        //入栈
                        queen[++rear] = temp;
                        temp = temp->next;
                        count++;
                }
                if(count != k)
                {
                        pre ->next = head;
                        break;
                }
                //出栈
                while(rear != -1){
                        pre->next = queen[rear--];
                        pre = pre ->next;
                }
                pre->next = temp;
                head = temp;
        }
        return newhead.next;
}

结果:

f1411c4722e0f4ddfeaad6d2280b8d6edc5.jpg

 

转载于:https://my.oschina.net/1024and1314/blog/3095129

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值