今天是秋招算法打卡第二天,题目是链表中的节点每k个一组翻转和合并两个排序的链表
题目1:链表中的节点每k个一组翻转
描述:
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样你不能更改节点中的值,只能更改节点本身。
数据范围:0≤n≤2000 , 1≤k≤2000 ,链表中每个元素都满足0≤val≤1000
要求空间复杂度 O(1),时间复杂度 O(n)
解题方法:
非递归:
1、遍历链表,获取链表长度length,并根据分组长度k,计算出链表所能划分的组数n
2、反转每一组链表,并使他们连接起来即可
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
public ListNode reverseKGroup (ListNode head, int k) {
// write code here
if(head == null || head.next == null || k == 1){
return head;
}
//虚拟头节点
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
//用于记录被反转链表的下一结点
//初始值为头节点
ListNode follow = pre.next;
//获取可以分成的组数
int n = num(head) / k;
//反转每一组链表
for(int j = 0; j < n; j++){
//被反转链表的最左节点
ListNode left = follow;
//被反转链表的最右节点
ListNode right = left;
for(int i = 1; i < k; i++){
right = right.next;
}
//反转链表的下一个节点
follow = right.next;
//截断被反转的链表
right.next = null;
reverseList(left);
pre.next = right;
pre = left;
}
//连接剩余节点
pre.next = follow;
return dummy.next;
}
//反转链表
public void reverseList(ListNode head){
ListNode pre = null;
while(head != null){
ListNode tmp = head.next;
head.next = pre;
pre = head;
head = tmp;
}
}
//获取链表长度
public int num(ListNode head){
ListNode index = head;
int length = 0;
while(index != null){
index = index.next;
length++;
}
return length;
}
}
问题2:合并两个排序的链表
描述:
输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
数据范围:0≤n≤1000,节点值−1000≤节点值≤1000
要求:空间复杂度 O(1),时间复杂度 O(n)
解题方法:
非递归
1、从头节点开始依次遍历两个链表的节点
2、比较两个链表节点的值,小的值加入合并链表
3、直到一个链表遍历完全,将另一个链表剩余部分加入合并链表
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode Merge(ListNode list1,ListNode list2) {
//虚拟头节点,以dummy作为合并链表
ListNode dummy = new ListNode(-1);
ListNode head = dummy;
//当两个链表都不为空时,比较节点的值,较小的加入新链表
//并将对应链表的节点移到下一个节点
while(list1 != null && list2 != null){
if(list1.val <= list2.val){
//并入较小值到链表
head.next = list1;
//移动节点
list1 = list1.next;
}
else{
head.next = list2;
list2 = list2.next;
}
head = head.next;
}
//如果某个链表遍历完了就将另一个链表的剩余节点并入链表
if(list1 == null){
head.next = list2;
}
if(list2 == null){
head.next = list1;
}
return dummy.next;
}
}