链表翻转(Reverse Linked List)
实现翻转链表的功能
方法一:原地翻转
1 | public class ReverseLinkedList { |
链表中环的入口结点
题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解题思路:
方法一:哈希法
- 遍历单链表的每个结点
- 如果当前结点地址没有出现在set中,则存入set中
- 否则,出现在set中,则当前结点就是环的入口结点
- 整个单链表遍历完,若没出现在set中,则不存在环
1 | public class Solution { |
方法二:双指针法
两个链表的第一个公共结点
问题描述
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
解题思路
试想一种理想情况:链表A头结点到结点8的长度与链表B头结点到结点8的长度相等,那么就可以用双指针。
-1. 初始化:指针ta指向链表A头结点,指针tb指向链表B头结点
-2. 如果ta == tb, 说明找到了第一个公共的头结点,直接返回即可。
-3. 否则,ta != tb,则++ta,++tb
显然图一中第一个公共结点为8,但是链表A头结点到8的长度为2,链表B头结点到8的长度为3,显然并不相等。 所以需要制造这种理想情况。
假设链表A长度为a, 链表B的长度为b,此时a != b
但是,a+b == b+a
因此,可以让a+b作为链表A的新长度,b+a作为链表B的新长度。
代码实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1==null || pHead2==null){
return null;
}
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while(p1 != p2){
p1 = p1 == null ? pHead2 : p1.next;
p2 = p2 == null ? pHead1 : p2.next;
return p1;
}
}
复杂链表的复制
题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路:
1 | public class Solution { |
链表中的节点每k个一组翻转
题目描述:
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
要求空间复杂度 O(1)
例如:
给定的链表是1->2->3->4->5
对于 k=2, 你应该返回 2→1→4→3→5
对于 k=3, 你应该返回 3→2→1→4→5