今天做了两道非常有意思的题目,leetcode上的206和234。这两道题目都是和链表有关的,并且都会运用的reverse list这个思想。
pro(206): Reverse a singly linked list.
My solution1:
如果是数组实现回非常简单,但是linkedlist如何实现?
第一个想法是,新建一个数组,遍历linkedlist中的所有元素,并记录在数组中。再遍历一次,此时修改在linked list中的每一个元素的值. 这个方法需要三次遍历.
public class Solution {
public ListNode reverseList(ListNode head) {
if(head == null) return null;
//第一次遍历,是用来计算链表中有多少个元素,即n
ListNode Num = head;
int n = 1;
while(Num.next != null){ //判断链表是否到头
Num = Num.next;
n++;
}
//第二次遍历,是用来在数组中纪录链表中的元素
ListNode Record = head;
int[] Val = new int[n];
for(int i = 0; i < n; i++){
Val[i] = Record.val;
Record = Record.next;
}
//第三次遍历,是用来反转的
ListNode Reverse = head;
for(int j = n-1; j >= 0; j--){
Reverse.val = Val[j] ;
Reverse = Reverse.next;
}
return head;
}
}
这是完全利用数组,那么如何治只利用链表呢?
My solution(2): 迭代
如果是双链表,进行reverse是非常简单的,因此我们可以借鉴双链表的方法来反转链表。这里我们需要三个node, pre , cur, next 分别代表当前,之前和之后的node.
public class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode pre = null;
ListNode next = null;
while(head != null){
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
}
My solution(3): 递归
利用递归!
public class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode cur = head.next;
ListNode res = reverseList(cur); //res是得到head之后的反转
head.next = null;
cur.next = head;
return res;
}
}
接下来我们看看leetcode的234题。
Pro:
Given a singly linked list, determine if it is a palindrome.
Follow up:Could you do it in O(n) time and O(1) space?
My solution(1):