持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情
1、前言
每天一个算法小练习,本篇使用Java实现。
2、题目描述
对于一个链表 L: L0→L1→…→Ln-1→Ln,将其翻转成 L0→Ln→L1→Ln-1→L2→Ln-2→…。输入是一串数字,请将其转换成单链表格式之后,再进行操作。
2.1、输入描述
一串用逗号分隔的数字
2.2、输出描述
一串用逗号分隔的数字
2.3、示例
输入:
1,2,3,4,5
输出:
1,5,2,4,3
3、解题思路
将链表分成两半,后半段逆序,然后与前半段进行合并。
-
1、利用快慢指针找到链表的中间节点;
-
2、通过遍历,使后半段链表逆序;
-
3、合并两个链表。
4、实现代码
public class ReverseListNode {
static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String[] inputStrArr = str.split(",");
ListNode head = new ListNode(-1);
ListNode rear = head;
//将输入数据都插入到链表中
for(String item : inputStrArr) {
ListNode newNode = new ListNode(Integer.parseInt(item));
rear.next = newNode;
rear = newNode;
}
reverseListNode(head.next);
head = head.next;
while(head!=null){
if(head.next==null){
System.out.print(head.val);
}else{
System.out.print(head.val+",");
}
head=head.next;
}
}
/**
* 链表分割成两段,后半段逆序,然后与前半段合并
* @param head
*/
public static void reverseListNode(ListNode head) {
if (head == null || head.next == null) {
return;
}
ListNode left = head;
ListNode right = head;
//利用快慢指针,找到链表的中间节点。快指针每次移动2步,慢指针每次1步
while (right.next != null && right.next.next != null) {
left = left.next;
right = right.next.next;
}
//将链表分为两段
right = left.next;
left.next = null;
left = head;
//把后半段链表逆序
ListNode head2 = right;
ListNode next2;
while (right.next != null) {
next2 = right.next;
right.next = next2.next;
next2.next = head2;
head2 = next2;
}
right = head2;
//合并
ListNode next1;
while (right != null) {
next1 = left.next;
next2 = right.next;
left.next = right;
right.next = next1;
left = next1;
right = next2;
}
}
}
5、执行结果
与预期一样
6、算法性能
6.1、时间复杂度
因为只需要从头到尾遍历一遍链表,所以时间复杂度为 ,就是需要翻转的链表的长度。
6.2、空间复杂度
实现过程中没有创建使用额外空间,所以为
好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊