力扣原题:旋转链表
先贴代码:
public class Solution61 {
public ListNode rotateRight(ListNode head, int k) {
//当链表为空或者链表只有一个元素或者移动0步的时候的情况
if (head == null || head.next == null || k == 0){
return head;
}
//创建一个虚拟头节点,指向head
ListNode newhead = new ListNode(-1);
newhead.next = head;
//求出链表长度
int len = 1;
ListNode cur = head;
while (cur.next != null){
cur = cur.next;
len++;
}
//进行头尾相连
cur.next = head;
//求出链表形成的环实际要走的步数a
int a = len-k%len;
//开始循环a步
while (a != 0){
newhead.next = newhead.next.next;
a--;
}
//将新头节点的上一个节点的next域置为空,使其从环再次变为链表
cur = newhead.next;
while (cur.next != newhead.next){
cur = cur.next;
}
cur.next = null;
//返回newhead的下一个节点,即是新的头节点
return newhead.next;
}
}
思路解析:题目中告诉我们,要将链表每一个节点向右移动k个位置,其实意思就是将链表最后一个节点放到开头来,重复进行k次而已。由此我们可以想到:将尾巴节点指向头节点,再重复进行k次,不就行了吗?的确,这种方法在第一次中是可行的,可是我们需要重复循环,在之后的操作中需要不断地找出尾巴节点以及尾巴节点的上一个节点,这样下来整个代码就变得极其复杂和浪费。那么有没有更简单的方法?
由题目中我们可以得知,我们需要不断地将尾巴节点前置为头节点,那么我们将此链表头尾相连,形成一个环形,再将它进行k次的旋转,不就可以将尾巴节点前置为头节点了吗?但是此时需要注意的一点是,题目中意思是要我们进行顺时针旋转,而我们将链表练成环后,只能进行逆时针旋转,因为在单向链表中只能指向下一个节点而无法指向上一个节点。
我们假设链表长度为n,那么连成环后,顺时针走k步,相当于逆时针走n-k步。明白这点后就可以很容易得出当链表移动k个位置时,就是我们的环逆时针走了n-k步。然后再进行循环,再将头节点上个节点的next域置为空,即可解决问题!