盲目刷题,浪费大量时间,博主这里推荐一个面试必刷算法题库,刷完足够面试了。传送门:牛客网面试必刷TOP101
🏄🏻作者简介:CSDN博客专家,华为云云享专家,阿里云专家博主,疯狂coding的普通码农一枚
🚴🏻♂️个人主页:莫逸风
👨🏻💻专栏题目地址👉🏻牛客网面试必刷TOP101👈🏻
🇨🇳喜欢文章欢迎大家👍🏻点赞🙏🏻关注⭐️收藏📄评论↗️转发
题目:链表中的节点每k个一组翻转
描述:
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
数据范围:0≤n≤2000 , 1≤k≤2000 ,链表中每个元素都满足 0≤val≤1000
要求空间复杂度 O(1),时间复杂度 O(n)
例如:
给定的链表是 1→2→3→4→5
对于 k = 2k=2 , 你应该返回 2→1→4→3→5
对于 k = 3k=3 , 你应该返回 3→2→1→4→5
思路:
思路一:堆栈
- 不考虑空间问题,队列、栈处理链表太方便了。
- 分段入栈。然后取出,注意处理最后一段取队头就好了(我下面代码用的是Deque,java中的双端队列)。
思路二:迭代
- 和BM02问题相同的处理方式,不过额外处理最后一段比较麻烦。
思路三:递归✅
- 推荐的处理方式,每次只处理一段,然后递归交给下面处理,本题非常适合用递归。
代码:
public class BM03 {
public static void main(String[] args) {
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(3);
ListNode listNode3 = new ListNode(5);
ListNode listNode4 = new ListNode(7);
ListNode listNode5 = new ListNode(9);
listNode1.next = listNode2;
listNode2.next = listNode3;
listNode3.next = listNode4;
listNode4.next = listNode5;
ListNode curListNode = listNode1;
while (curListNode!=null){
System.out.println(curListNode.val);
curListNode = curListNode.next;
}
curListNode = reverseKGroup3(listNode1,2);
while (curListNode!=null){
System.out.println(curListNode.val);
curListNode = curListNode.next;
}
}
/**
* 堆栈
*/
public static ListNode reverseKGroup (ListNode head, int k) {
// write code here
ListNode pre = new ListNode(-1);
ListNode curr = pre;
pre.next = head;
Deque<ListNode> deque = new ArrayDeque<>();
ListNode cur = head;
int i = 0;
while (cur!=null){
i++;
deque.add(cur);
cur = cur.next;
if (i%k==0){
while (!deque.isEmpty()){
curr.next = deque.pollLast();
curr = curr.next;
}
}
}
curr.next = null;
if (!deque.isEmpty()){
curr.next = deque.pollFirst();
}
return pre.next;
}
/**
* 迭代
*/
public static ListNode reverseKGroup2 (ListNode head, int k) {
ListNode pre = new ListNode(-1);
ListNode result = pre;
pre.next = head;
ListNode cur = head;
ListNode temp;
int i = 0;
ListNode next;
while (cur!=null){
i++;
if (i%k==0){
pre = cur;
cur = cur.next;
next = cur;
// 判断后续是否足够反转
for (int j = 0; j < k; j++) {
if (next == null){
return result.next;
}
next = next.next;
}
}else {
temp = cur.next;
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
}
}
return result.next;
}
/**
* 分组递归
*/
public static ListNode reverseKGroup3(ListNode head, int k) {
ListNode tail = head; //找到每次翻转的尾部
for(int i = 0; i < k; i++){ //遍历k次到尾部
if(tail == null) //如果不足k到了链表尾,直接返回,不翻转
return head;
tail = tail.next;
}
ListNode pre = null; //翻转时需要的前序和当前节点
ListNode cur = head;
while(cur != tail){ //在到达当前段尾节点前
ListNode temp = cur.next; //翻转
cur.next = pre;
pre = cur;
cur = temp;
}
head.next = reverseKGroup3(tail, k); //当前尾指向下一段要翻转的链表
return pre;
}
}
推荐牛客网面试必刷算法题库,刷完足够面试了。传送门:牛客网面试必刷TOP101