链表的一些简单题型
- 反转链表
- 链表中倒数第k个节点
- 从尾到头打印链表
- 判断链表中是否有环
- 链表中环的起始点
剑指Offer 24. 反转链表
参考网址:https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/
示例代码:(双指针)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
import java.util.*;
class Solution {
public ListNode reverseList(ListNode head) {
ListNode result = null;
if (head == null) return result;
while(head != null){
ListNode index = head.next;
head.next = result;
// 指针移位
result = head;
head = index;
}
return result;
}
}
方法二
/**
原链表的头结点就是反转之后链表的尾结点,使用 head标记 .
定义指针 cur,初始化为 head .
每次都让 head 下一个结点的 next 指向 cur ,实现一次局部反转
局部反转完成之后,cur 和 head 的 next 指针同时 往前移动一个位置
循环上述过程,直至 cur 到达链表的最后一个结点 .
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode result = head;
while(head != null && head.next != null){
ListNode index = head.next.next;
head.next.next = result;
// result移位与head的下一节点指向head.next.next
result = head.next;
head.next = index;
}
return result;
}
}
剑指Offer 22. 链表中倒数第k个节点
双指针(指针间隔为k-1)无需统计链表长度
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode result = head;
while(head != null && head.next != null){
if (k > 1){
head = head.next;
k--;
} else {
head = head.next;
result = result.next;
}
}
return result;
}
}
剑指 Offer 06. 从尾到头打印链表
参考网址:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/
方法一:辅助栈
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public int[] reversePrint(ListNode head) {
Stack<Integer> index = new Stack<Integer>();
while(head != null){
index.push(head.val);
head = head.next;
}
int[] result = new int[index.size()];
int numIndex = 0;
while(!index.empty()){
result[numIndex] = index.pop();
numIndex++;
}
return result;
}
}
方法二:遍历长度后从尾到头填充数组
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public int[] reversePrint(ListNode head) {
int length = 0;
ListNode swap = head;
while(swap != null){
swap = swap.next;
length++;
}
int[] result = new int[length];
while(head != null){
result[length-1] = head.val;
head = head.next;
length--;
}
return result;
}
}
LeetCode 第141题. 环形链表
网址:https://leetcode-cn.com/problems/linked-list-cycle/
解题思路:快慢指针
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode first = head;
ListNode secord = head;
if (head == null){
return false;
}
while(first != null && first.next != null){
first = first.next.next;
secord = secord.next;
if (first == secord){
return true;
}
}
return false;
}
}
LeetCode 第141题. 环形链表II
网址:https://leetcode-cn.com/problems/linked-list-cycle-ii/
输出链表中环的起始点位置
解题思路:快慢指针加简单的数学计算
- 时间为t
- 慢指针的速度为1 ; 路程为 t
- 快指针的速度为2 ; 在环中跑了n圈 ;路程为 2t
由于快慢指针的速度分别为1和2,那么快指针必然比慢指针多跑一圈后相遇,且慢指针必然是第一次进入环中,且未跑完一圈就相遇
slow指针走过的节点数为: x + y = t
fast指针走过的节点数: x + y + n (y + z) = 2t
即 x+y = n(y+z) 且n为1
故 x = z
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
// 快慢指针
ListNode result = null;
ListNode slow = head;
ListNode fast = head;
while (fast != null){
slow = slow.next;
if (fast.next != null){
fast = fast.next.next;
} else {
return result;
}
if(slow == fast){
result = head;
while(result != slow){
result = result.next;
slow = slow.next;
}
return result;
}
}
return result;
}
}