Leetcode-206 反转链表
题目
给你单链表的头节点
head ,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
- 链表中节点的数目范围是
[0, 5000] -5000 <= Node.val <= 5000
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
我的思路
设置一个临时数组存储链表元素,再将临时数组中的链表元素倒序存放入一个新链表中
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode reverseList(ListNode head) { if(head != null){ ListNode reverseList = new ListNode(); ListNode tempNode = head; List<Integer> tempList = new ArrayList<Integer>(); while(tempNode != null){ tempList.add(tempNode.val); tempNode = tempNode.next; } reverseList.val = tempList.get(tempList.size()-1); reverseList.next = null; tempNode = reverseList; for(int i = tempList.size()-2; i >= 0; --i){ ListNode temp = new ListNode(); temp.val = tempList.get(i); temp.next = null; tempNode.next = temp; tempNode = temp; } return reverseList; } else{ return head; } } }
这个思路空间复杂度为O(n),下面参考了别人的更简洁的写法,主要是利用了链表之间的节点连接,连接一个结点就相当于将该节点的后续结点都连接了。
class Solution { public ListNode reverseList(ListNode head) { ListNode ans = null; for (ListNode x = head; x != null; x = x.next) { //ans就是前一个结点,ans赋值后为当前结点,每次实例化节点后都连接好节点了 ans = new ListNode(x.val,ans); } return ans; } }
迭代法
将当前节点的next指针指向前一个节点,要注意保存好前一个节点的指针。还有要有一个当前节点的指针,用于迭代。临时指针,用于交换。使用while循环
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { //使用迭代法反转链表 public ListNode reverseList(ListNode head) { //需要有一个pre指针,保存前一个结点 ListNode preNode = null; //还需要一个当前节点的指针,方便迭代 ListNode currNode = head; //临时节点,方便交换用的 ListNode tempNode = null; while(currNode != null){ tempNode = currNode.next; currNode.next = preNode; preNode = currNode; currNode = tempNode; } /** head = preNode; 没有必要进行这一步,因为preNode本就为null,如果head为null,直接返回pre也是null */ return preNode; } }
递归法
先进入最后一层(调用递归函数),然后返回给前面的层进行连接(进行实际地处理反转)。要注意递归的结束条件(什么时候直接返回,不会进行实际处理反转),到达最后一层的条件为head.next为null,但是head为null也不能进入递归(即直接返回)。还有要注意当前层要做什么事(把当前层连接到反转好的链表中)
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { //使用递归法反转链表 public ListNode reverseList(ListNode head) { //递归用if语句判断终止条件(返回条件) if(head == null || head.next == null){ //当到达最后一层时,返回的就是最后一个节点的指针 return head; } //反转head后面的节点 ListNode newHead = reverseList(head.next);//newHead为反转链表的头节点 //处理当前head节点 head.next.next = head;//将当前层head下一个节点的next指针连接到head作反转 head.next = null; return newHead; } }
学到和回忆了
- 在处理链表等问题时,首先要判断链表是否为空
- 在Java中,判断集合元素数量和添加元素的方法是size()和add()
- 在Java中,ArrayList可以随机访问,但不能使用[]访问下标,而只能使用get()方法访问下标
- 在Java中,泛型只能是包装类而不能是基本数据类型
- 在Java中,必须要显示判断变量是否为null
浙公网安备 33010602011771号