程序员代码面试指南第二版 16.反转部分单向链表
题目描述
给定一个单链表,在链表中把第 L 个节点到第 R 个节点这一部分进行反转。
输入描述:
n 表示单链表的长度。
val 表示单链表各个节点的值。
L 表示翻转区间的左端点。
R 表示翻转区间的右端点。
输出描述:
在给定的函数中返回指定链表的头指针。
示例1
输入
5
1 2 3 4 5
1 3
输出
3 2 1 4 5
第一次做, 这道题挺难的, 主要是很细; 核心: 1)找到fromLeft节点和toRight节点; 2)从待反转链表的第二个节点开始反转 3)待反转链表的头结点一定指向toRight 4)待反转链表的尾结点稍微复杂些, 如果该尾结点是整体链表的头结点, 就没有东西的next指向它了; 如果该尾结点不是整体链表的头结点, 就会有fromLeft.next指向该尾结点; 题外话: 注意反转可以通过交换实现,例子:1,2,3反转成3,2,1可以用交换实现; 1,2,3,4反转成4,3,2,1可以用交换实现
import java. util. Scanner;
public class Main {
public static void main ( String[ ] args) {
Scanner sc = new Scanner ( System. in) ;
int n = Integer. parseInt ( sc. nextLine ( ) ) ;
String[ ] str = sc. nextLine ( ) . split ( " " ) ;
String s = sc. nextLine ( ) ;
int l = Integer. parseInt ( s. split ( " " ) [ 0 ] ) ;
int r = Integer. parseInt ( s. split ( " " ) [ 1 ] ) ;
if ( l> r || l< 1 || r> n)
return ;
ListNode head = new ListNode ( Integer. parseInt ( str[ 0 ] ) ) ;
ListNode curr = head;
for ( int i= 1 ; i< n; i++ ) {
curr. next = new ListNode ( Integer. parseInt ( str[ i] ) ) ;
curr = curr. next;
}
int len= 1 ;
curr = head;
ListNode fromLeft= null, toRight= null;
while ( curr!= null) {
if ( len== l- 1 )
fromLeft = curr;
if ( len== r+ 1 )
toRight = curr;
len++ ;
curr = curr. next;
}
ListNode left = fromLeft== null? head : fromLeft. next;
curr = left. next;
left. next = toRight;
ListNode right;
while ( curr!= toRight) {
right = curr. next;
curr. next = left;
left = curr;
curr = right;
}
if ( fromLeft== null)
head = left;
else
fromLeft. next = left;
curr = head;
while ( curr!= null) {
System. out. print ( curr. val+ " " ) ;
curr = curr. next;
}
}
public static class ListNode {
int val;
ListNode next;
ListNode ( int val) {
this . val = val;
}
}
}