1.直接反转一个链表
这个题目在面试中是会考察的,因为代码量很少,要掌握
class Solution{
public ListNode reverseList(ListNode head) {
ListNode cur = head, pre = null;
while(cur!=null){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
这个是要直接写出来的,包括手写
2.反转一段链表的第n个节点到第m个节点
这个有种种边界条件要考虑,是不容易一次性就正确的写出来的。
优雅的代码是封装一个函数,反转从begin节点到end节点之间的节点。
这里要注意,反转的链表是不包括begin和end,原因是反转中间链表会影响到两边,为了代码的高内聚,低耦合,应该把两边的begin和end也加上
public ListNode reverse(ListNode begin, ListNode end)
这里的反转逻辑如下
/* 1->2->3->4->5
1<- 2<- 3 <- 4 ->5
| | | |
begin first pre cur
1->4->3->2->5
*/
除了中间反转逻辑,还有前后的处理,为了检验这段代码的鲁棒性,可以传入dummy和null来验制反转整个链表
public ListNode reverse(ListNode begin, ListNode end){
ListNode cur = begin.next, pre = begin, first = cur; // first 作为尾节点返回
while(cur!=end) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
begin.next = pre;
first.next = cur;
return first;
}
3. K个链表反转一次
这个是最难的题目,首先要实现上面的函数,同时还要有遍历逻辑,要边画图边思考,面试中做出来还是不容易。
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
int count = 0;
ListNode cur = dummy.next, begin = dummy, end = null;
while(cur!=null){
count++;
if(count%k==0){
begin = reverse(begin, cur.next);
cur = begin.next;
}
else{
cur = cur.next;
}
}
return dummy.next;
}
/*
翻转begin到end之间的链表(不包括begin和end, 并返回最后一个节点)
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
1 1<-2<-3<-4->5
*/
public ListNode reverse(ListNode begin, ListNode end){
ListNode cur = begin.next, pre = begin, first = cur; // first 作为尾节点返回
while(cur!=end) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
begin.next = pre;
first.next = cur;
return first;
}
}