剑指offer52
先将第一个链表元素全部存到Map里,然后一边遍历第二个链表,一边检测当前元素是否在Hash中,如果两个链表有交点,那就找到了。
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> firstSet = new HashSet<>();
for (ListNode p = headA; p != null; p = p.next) {
firstSet.add(p);
}
for (ListNode p = headB; p != null; p = p.next) {
if (firstSet.contains(p)) {
return p;
}
}
return null;
}
}
将两个链表分别压到两个栈里,之后一边同时出栈,一边比较出栈元素是否一致,如果一致则说明存在相交,然后继续找,最晚出栈的那组一致的节点就是要找的位置
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Stack<ListNode> stack1 = new Stack<>();
Stack<ListNode> stack2 = new Stack<>();
ListNode p1 = headA;
while (p1 != null) {
stack1.push(p1);
p1 = p1.next;
}
ListNode p2 = headB;
while (p2 != null) {
stack2.push(p2);
p2 = p2.next;
}
ListNode pubNode = null;
while (!stack1.empty() && !stack2.empty()) {
ListNode s1 = stack1.pop();
ListNode s2 = stack2.pop();
if (Objects.equals(s1, s2)) {
pubNode = s1;
}
}
return pubNode;
}
}
先看下面的链表A和B:
A: 0-1-2-3-4-5
B: a-b-4-5
如果分别拼接成AB和BA会怎么样呢?
AB:0-1-2-3-4-5-a-b-4-5
BA:a-b-4-5-0-1-2-3-4-5
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null)
return null;
ListNode p1, p2;
p1 = headA;
p2 = headB;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
if (p1 != p2) {
if (p1 == null) p1 = headB;
if (p2 == null) p2 = headA;
}
}
return p1;
}
}
假如公共子节点一定存在第一轮遍历,假设La长度为L1,Lb长度为L2.则|L2-L1|就是两个的差值。第二轮遍历,长的先走|L2-L1|,然后两个链表同时向前走,结点一样的时候就是公共结点了。
class Solution {
public ListNode getIntersectionNode(ListNode pHead1, ListNode pHead2) {
if(pHead1==null || pHead2==null){
return null;
}
ListNode current1=pHead1;
ListNode current2=pHead2;
int l1=0,l2=0;
//分别统计两个链表的长度
while(current1!=null){
current1=current1.next;
l1++;
}
while(current2!=null){
current2=current2.next;
l2++;
}
current1=pHead1;
current2=pHead2;
int sub=l1>l2?l1-l2:l2-l1;
//长的先走sub步
if(l1>l2){
int a=0;
while(a<sub){
current1=current1.next;
a++;
}
}
if(l1<l2){
int a=0;
while(a<sub){
current2=current2.next;
a++;
}
}
//同时遍历两个链表
while(current2!=current1){
current2=current2.next;
current1=current1.next;
}
return current1;
}
}
LeetCode234
将链表元素全部压栈,然后一边出栈,一边重新遍历链表,一边比较两者元素值,只要有一个不相等,那就不是。
class Solution {
public boolean isPalindrome(ListNode head) {
Stack<ListNode> stack = new Stack<>();
ListNode p = head;
while (p != null) {
stack.add(p);
p = p.next;
}
p = head;
while (p != null) {
ListNode p2 = stack.pop();
if (p.val != p2.val)
return false;
p = p.next;
}
return true;
}
}
LeetCode21
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode dummyHead = new ListNode();
ListNode p1 = list1, p2 = list2, dummy = dummyHead;
while (p1 != null && p2 != null) {
if (p1.val <= p2.val) {
dummy.next = p1;
dummy = dummy.next;
p1 = p1.next;
} else {
dummy.next = p2;
dummy = dummy.next;
p2 = p2.next;
}
}
if (p1 == null) {
dummy.next = p2;
} else {
dummy.next = p1;
}
return dummyHead.next;
}
}
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode dummy = null;
for (ListNode node : lists) {
dummy = merge2List(dummy, node);
}
return dummy;
}
public ListNode merge2List(ListNode list1, ListNode list2) {
ListNode dummy = new ListNode();
ListNode p = dummy, p1 = list1, p2 = list2;
while (p1 != null && p2 != null) {
if (p1.val <= p2.val) {
p.next = p1;
p1 = p1.next;
} else {
p.next = p2;
p2 = p2.next;
}
p = p.next;
}
if (p1 == null) {
p.next = p2;
} else {
p.next = p1;
}
return dummy.next;
}
}
LeetCode1669
class Solution {
public ListNode mergeInBetween(ListNode list1, int a, int b, ListNode list2) {
ListNode p = list1, aBefore, bAfter;
for (int i = 0; i < a - 1; i++){
p = p.next;
}
aBefore = p;
for (int i = 0; i< b - a + 2; i++) {
p = p.next;
}
bAfter = p;
aBefore.next = list2;
p = list2;
while (p.next != null) {
p = p.next;
}
p.next = bAfter;
return list1;
}
}
LeetCode876
class Solution {
public ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
LeetCode22
这里也可以使用快慢双指针,我们先将fast 向后遍历到第 k+1 个节点, slow仍然指向链表的第一个节点,此时指针fast 与slow 二者之间刚好间隔 k 个节点。之后两个指针同步向后走,当 fast 走到链表的尾部空节点时,slow 指针刚好指向链表的倒数第k个节点。
这里需要特别注意的是链表的长度可能小于k,寻找k位置的时候必须判断fast是否为null,这是本题的关键问题之一
Leetcode203
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(-1, head);
ListNode p = dummy;
while (p.next != null) {
if (p.next.val == val) {
p.next = p.next.next;
} else {
p = p.next;
}
}
return dummy.next;
}
}
LeetCode82
public ListNode deleteDuplicates(ListNode head) {
ListNode dummy = new ListNode(-1, head);
ListNode prev = dummy;
while (prev.next != null && prev.next.next != null) {
if (prev.next.val == prev.next.next.val) {
int val = prev.next.val;
while (prev.next != null && prev.next.val == val) {
prev.next = prev.next.next;
}
} else {
prev = prev.next;
}
}
return dummy.next;
}