1、反转链表
//给你单链表的头节点 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 // // // // // 进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题? // // // Related Topics 链表
1、迭代法
其基本思路在于不断遍历链表,在当前元素前插入新元素,直到列表给遍历完
public ListNode reverseList(ListNode head) {
//迭代
ListNode next = null;
ListNode curr = head;
while(curr != null){
ListNode prev = curr.next;
curr.next = next;
next = curr;
curr = prev;
}
return next;
}
2、递归法
递归法在于改变指向,但又不让链表中出现环
这里可以参考官方题解:
public ListNode reverseList(ListNode head) {
//递归
if(head == null || head.next == null){
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
//这样就不会在链表中出现环
head.next = null;
return newHead;
}
2、判断链表是否回文
//请判断一个链表是否为回文链表。 // // 示例 1: // // 输入: 1->2 //输出: false // // 示例 2: // // 输入: 1->2->2->1 //输出: true // // // 进阶: //你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题? // Related Topics 链表 双指针
这题的两种解法都比较一般,在这里不多加赘述
1、先转成数组再判断回文
public boolean isPalindrome(ListNode head) {
//转成数组再进行回文判断
ArrayList<Integer> vals = new ArrayList<>();
ListNode currentNode = head;
while(currentNode != null){
vals.add(currentNode.val);
currentNode = currentNode.next;
}
int front = 0;
int back = vals.size()-1;
while(front < back){
if(!vals.get(front).equals(vals.get(back))){
return false;
}
front++;
back--;
}
return true;
}
2、先用快慢指针找到中间节点,然后反转后半链表,一一对比判断是否回文,最后恢复链表。
public boolean isPalindrome(ListNode head) {
//快慢指针法
if(head == null){
return true;
}
//1、找到前半部分链表的尾结点并反转后半部分链表
ListNode firstHalfEnd = endofFirstHalf(head);
ListNode secondHalfStart = reverseList(firstHalfEnd.next);
//2、判断是否回文
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while (result && p2 != null) {
if (p1.val != p2.val) {
result = false;
}
p1 = p1.next;
p2 = p2.next;
}
// 还原链表并返回结果
firstHalfEnd.next = reverseList(secondHalfStart);
return result;
}
private ListNode endofFirstHalf(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}