题意:
反转一个单链表。
初步分析:
开始画图,把这个流程表示出来了就可以了。
核心点:1 对结点操作 2 将操作结点往后移
对结点的操作核心是:结点的next应该是要指向下一个结点的,现在应该指向上一个。,所以:
1首先应该是将要操作的结点的下一个结点留存下来,
留存结点p ---------->....->...
要操作的结点head ---> 要操作的下一个结点---------->...->...
ListNode p = head.next;
将head的next连为前一个(开始循环之前的pre应该是头结点的上一个即null),开始循环之后的pre应该是上一次循环留存好的。
head.next = pre;
至此核心的操作已经结束,现在要做的就是移动操作点:
首先将当前操作结点留存为pre
pre = head;
然后设置新的操作结点(就要用到一开始留存的了)
head = p;
注意最后一步:heaad->next为空的时候,说明这个时候head是最后一个操作结点,但是每次对结点的操作都是在下一次循环才做的。但是下一次循环不会执行,所以要在循环结束后操作。
head.next = pre;
小结:
其实就是对于常规情况的流程要一步步的想清楚(画图)。对于边界情况等等其实也在脑子里想象清楚,应该就没什么问题。
/*
*
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode reverseList(ListNode head) {
if(head == null)
return head;
ListNode pre = null;
while(head.next!=null)
{
ListNode p = head.next;
head.next = pre;
pre = head;
head = p;
}
head.next = pre;
return head;
}
}
循环要改成迭代就很好改了:
我们循环中每次需要使用到上一次循环赋值的变量总共是两个,所以我们迭代中也传这两个参数。一个是要改连前面的那个结点,一个是要改连的结点,作为参数。
注意:调用第一次迭代的参数 对应 我们第一次循环时候的结点
在迭代中先写结束条件,对应 循环结束条件
在迭代中进行操作 对应 在循环中进行操作
在迭代中循环调用时候的参数 对应 循环中下一次循环要用到的参数。(这里也是迭代的方便所在)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode reverseList(ListNode head) {
if(head == null)
return head;
return reverse(null, head);
// ListNode pre = null;
// while(head.next!=null)
// {
// ListNode p = head.next;
// head.next = pre;
// pre = head;
// head = p;
// }
// head.next = pre;
// return head;
}
public ListNode reverse(ListNode pre, ListNode head)
{
if(head.next == null)
{
head.next = pre;
return head;
}
ListNode p = head.next;
head.next = pre;
return reverse(head, p);
}
}