LeetCode 25. K 个一组翻转链表

て烟熏妆下的殇ゞ 提交于 2020-07-29 10:53:02

我的LeetCode:https://leetcode-cn.com/u/ituring/

我的LeetCode刷题源码[GitHub]:https://github.com/izhoujie/Algorithmcii

LeetCode 25. K 个一组翻转链表

题目

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例:

给你这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明:

  • 你的算法只能使用常数的额外空间。
  • 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

思路1-先分为k段,每段翻转后拼接回去

先对原节点每k个节点分割,每个子段进行翻转,然后再处理拼接回去;

算法复杂度:

  • 时间复杂度: $ {\color{Magenta}{\Omicron\left(n\right)}} $
  • 空间复杂度: $ {\color{Magenta}{\Omicron\left(k\right)}} $

思路2-直接递归处理分段及分段翻转

每k个段记录并递归,从最后k个段向上递归翻转拼接,节点处理比较绕;

算法复杂度:

  • 时间复杂度: $ {\color{Magenta}{\Omicron\left(n\right)}} $
  • 空间复杂度: $ {\color{Magenta}{\Omicron\left(n\right)}} $

算法源码示例

package leetcode;

/**
 * @author ZhouJie
 * @date 2020年1月13日 下午10:25:53 
 * @Description: 25. K 个一组翻转链表
 *
 */
public class LeetCode_0025 {

}

// Definition for singly-linked list.
class ListNode_0025 {
	int val;
	ListNode_0025 next;

	ListNode_0025(int x) {
		val = x;
	}
}

class Solution_0025 {
	/**
	 * @author: ZhouJie
	 * @date: 2020年2月4日 下午3:15:23 
	 * @param: @param head
	 * @param: @param k
	 * @param: @return
	 * @return: ListNode_0025
	 * @Description: 1-迭代;
	 *
	 */
	public ListNode_0025 reverseKGroup(ListNode_0025 head, int k) {
		ListNode_0025 p1, p2, p3, newHead;
		p1 = p2 = p3 = newHead = null;
		int n = 1;
		ListNode_0025 dummy = new ListNode_0025(0);
		dummy.next = head;
		while (head != null) {
			dummy.next = head;
			while (head != null && n < k) {
				head = head.next;
				n++;
			}
			if (n < k || head == null) {
				break;
			}
			p2 = head;
			p3 = head.next;
			head.next = null;
			// 翻转一段链表
			reverse(null, dummy.next);
			if (newHead == null) {
				newHead = p2;
			} else {
				p1.next = p2;
			}
			p1 = dummy.next;
			p1.next = p3;
			head = p3;
			n = 1;
		}
		return newHead == null ? dummy.next : newHead;
	}

	/**
	 * @author: ZhouJie
	 * @date: 2020年2月4日 下午3:20:04 
	 * @param: @param tail
	 * @param: @param head
	 * @param: @return
	 * @return: ListNode_0025
	 * @Description: 翻转链表
	 *
	 */
	private ListNode_0025 reverse(ListNode_0025 tail, ListNode_0025 head) {
		if (head == null) {
			return tail;
		}
		ListNode_0025 next = head.next;
		head.next = tail;
		return reverse(head, next);
	}

	/**
	 * @author: ZhouJie
	 * @date: 2020年2月4日 下午3:26:30 
	 * @param: @param head
	 * @param: @param k
	 * @param: @return
	 * @return: ListNode_0025
	 * @Description: 2-递归;
	 *
	 */
	public ListNode_0025 reverseKGroup_2(ListNode_0025 head, int k) {
		ListNode_0025 now = head;
		int count = 0;
		while (now != null && count < k) {
			now = now.next;
			count++;
		}
		if (count == k) {
			now = reverseKGroup_2(now, k);
			// head是满足连续k个的最后一段首节点,now是最后一段尾节点的下一个节点
			while (count-- > 0) {
				ListNode_0025 temp = head.next;
				head.next = now;
				now = head;
				head = temp;
			}
			// 返回当前段处理完后的头结点
			return now;
		}
		return head;
	}
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!