Reverse_Nodes_in_kGroup

题目描述:

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list.
If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
(每k个一组翻转链表)
For example,

Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
思路1:翻转每k组序列直到剩余的序列不足k个,reverse的是将end指向节点放到start指向节点之后,之后将刚刚交换到前面的节点,用start指向,并且从start处向后推k-times-1个节点找到end应该指向的位置,之后重复以上操作直到剩余不够k个.假设有n个节点,翻转链表O(k^2),一共翻转n/k次,O(k^2*(n/k))==O(kn),,reverse中node是k组序列起始点的前一个节点。

public static ListNode reverse(ListNode node,int k)
	{
		//一共交换的次数
		int times = 0;
		//start和end的位置是交换起点与交换终点的前一个节点
		ListNode start = node;
		ListNode end = node;
		//遍历整个交换过程
		while(times<k-1)
		{
			//end指针移动的次数
			int count = 0;
			//结尾指针移动,k刚好比n大1时,会刚好停留在最后一个节点,导致检测不到
			while(count<(k-times-1))
			{
				//如果剩余的不够k个,那么便不对剩余节点做处理
				if(end.next==null)					
					return null;
				end = end.next;
				count++;
			}
			//处理k刚好比n大1的情况
			if(end.next==null)
				return null;
			//交换起始节点和结尾节点
			ListNode next = end.next.next;
			end.next.next = start.next;
			start.next = end.next;
			end.next = next;
			
			start = start.next;
			end = start;
			
			times++;
		}
		//返回下一个k组序列的前一个节点
		return start.next;
	}
	
	public static ListNode reverseKGroup(ListNode head, int k) 
	{
		if(head==null||k<=0)
			return null;
		
		ListNode root = new ListNode(0);
		root.next = head;		
		ListNode point = root;
				
		while(point!=null)
		{
			ListNode start = reverse(point,k);
			//k大于链表长度的处理
			if(point==root&&start==null)
				return root.next;
			point = start;
		}
		return root.next;
    }
思路二:翻转每k组序列直到剩余的序列不足k个,不同点在于reverse函数的改变,该reverse函数是将k序列第二到最后一个节点依次放到k序列第一个节点的前一个节点之后,直到原来的第一个节点到k序列的最后这样就完成了翻转。假设有n个节点,翻转k序列时间复杂度为O(k),需要翻转n/k次,所以时间复杂度为O(n)。

public static ListNode reverseKGroup(ListNode head, int k) 
	{ 
		if(head==null||k<=0)
			return null;
		
		ListNode root = new ListNode(0);
		root.next = head;
		ListNode start = root;
		ListNode end = root.next;
		int count = 0;
		while(end!=null)
		{
			count++;
			end = end.next;
			//剩余节点够k个才进行翻转
			if(count==k)
			{
				start = reverse(start,end);
				count = 0;
			}			
		}		
		return root.next;
	}
	//start是k序列第一个节点的前一个节点,end是k序列的最后一个节点的后一个节点
	public static ListNode reverse(ListNode start,ListNode end)
	{
		ListNode mark = start.next;
		ListNode point = start.next.next;
		while(point!=end)
		{
			ListNode next = point.next;
			point.next = start.next;
			start.next = point;
			mark.next = next;
			point = next;			
		}
		//返回下一个k序列第一个节点的前一个节点
		return mark;
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值