package java_core.Node;
import java.util.*;
/* 环形链表 141
输入一个链表的头结点, 判断该链表是否是环形链表
https://leetcode-cn.com/problems/linked-list-cycle/solution/huan-xing-lian-biao-by-leetcode/
*/
public class NodeTest {
public static void main(String[] args) {
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(4);
node1.next = node2;
ListNode node3 = new ListNode(3);
node2.next = node3;
ListNode node4 = new ListNode(5);
//node3.next = node4;
ListNode node5 = new ListNode(6);
node4.next = node5;
ListNode node6 = new ListNode(4);
node5.next = node6;
getNodes(node5);
getNodes(node6);
ListNode node = myaddTwoNumbers(node6, node5);
getNodes(node);
//System.out.println(myisPalindrome1(node4));
// getNodes(myreverseList2(node1));
}
//----------------------------------------------------------------------------------------------------------------------
//141 环形链表 start------------------------
//141. 1.哈希表法
public boolean myhasCycle1(ListNode head) {
Set<ListNode> set = new HashSet<>();
ListNode node = head;
//将节点添加入Set中,如果下一个节点能在Set中找到说明是环形链表
while (node != null) {
if (set.contains(node)) {
return true;
}
set.add(node);
node = node.next;
}
return false;
}
// 141. 2, 双指针法:使用一个快指针一个慢指针一起遍历,如果是环形链表,那么他们迟早会相遇
public boolean hasCycle2(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
// 141 环形链表 end--------------------------------
//----------------------------------------------------------------------------------------------------------------------
//83.删除排序链表的重复元素 start----------------------
//me
private static ListNode deleteRenode(ListNode head) {
if (head == null) {
return null;
} else {
ListNode curr = head;
while (curr.next != null) {
ListNode next = curr.next;
//如果下一个节点值和当前节点相同,则将当前节点的next指向下下个节点,不相同则将下一个节点设为当前节点
if (next.val == curr.val) {
curr.next = next.next;
} else {
curr = next;
}
}
return head;
}
}
class Solution {
//83
public ListNode deleteDuplicates(ListNode head) {
ListNode cur = head;
while (cur != null && cur.next != null) {
if (cur.val == cur.next.val) {
ListNode node = cur.next;
cur.next = node.next;
node.next = null;//清除野指针
} else {
cur = cur.next;
}
}
return head;
}
}
//83.删除排序链表的重复元素 end----------------------
//----------------------------------------------------------------------------------------------------------------------
//82. 删除排序链表中的重复元素 II 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
// https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/
public static ListNode deleteDuplicates(ListNode head) {
if (head == null) {
return null;
}
// 1. 创建一个首节点,处理原先的首节点被删除的情况
ListNode first = new ListNode(0);
first.next = head;
ListNode curr = head;
ListNode pre = first;
ListNode next;
boolean f = false;
while (curr != null) {
next = curr.next;
if (next == null) {
return first.next;
}
//查看是否有重复节点
while (curr.val == next.val) {
f = true;
next = next.next;
if (next == null) {
pre.next = null;
return first.next;
}
}
//有重复节点
if (f) {
//将前一个节点的next指向next
pre.next = next;
curr = next;
f = false;
} else {
//没有重复节点
pre = curr;
curr = next;
}
}
return first.next;
}
//----------------------------------------------------------------------------------------------------------------------
//206 反转链表 start ---------------------------------------
//206.反转链表 Yes
private static ListNode myreverseNode1(ListNode head) {
if (head == null) {
return null;
} else {
if (head.next == null) {
return head;
}
ListNode curr = head;
//首节点
ListNode first = head;
ListNode next;
//反转的过程:1.将下一个节点的next指向首节点;2.将当前节点的next指向下下个节点
while (curr.next != null) {
//1. 先用一个指针记录住下一个节点
next = curr.next;
//2.将当前指针的next指向下下个节点
curr.next = next.next;
//3.将原先记录下来的下一个节点的next指向首节点
next.next = first;
//4.更新首节点
first = next;
}
return first;
}
}
//206 OK
public static ListNode myreverseList2(ListNode head) {
ListNode pre = null;
ListNode cur = head;//当前节点
while (cur != null) {
ListNode next = cur.next;//先将下一个节点保存
cur.next = pre;//当前节点的指针指向上一个节点
pre = cur;//更新循环
cur = next;
}
return pre;
}
// ok
public static 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;
}
//206. 反转链表 end----------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// 234.回文链表: 1->2->2->1
// https://leetcode-cn.com/problems/palindrome-linked-list/
// 1. me 遍历到数组中, 通过数组双指针判断是否回文
public static boolean myisPalindrome1(ListNode head) {
if (head == null) {
//空字符串也属于回文
return true;
}
List<Integer> list = new ArrayList<>();
while (head != null) {
list.add(head.val);
head = head.next;
}
int left = 0;
int right = list.size() - 1;
while (left < right) {
if (!list.get(left++).equals(list.get(right--))) {
return false;
}
}
return true;
}
//----------------------------------------------------------------------------------------------------------------------
// 2. 两数相加 no
public static ListNode myaddTwoNumbers(ListNode l1, ListNode l2) {
ListNode curr1 = l1;
ListNode curr2 = l2;
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
while (l1 != null) {
list1.add(l1.val);
l1 = l1.next;
}
while (l2 != null) {
list2.add(l2.val);
l2 = l2.next;
}
int length1 = list1.size();
int length2 = list2.size();
if (length1 >= length2) {
ListNode one = curr1;
for (int i = 0; i < length1; i++) {
if (i == 0) {
curr1.val = 0;
}
if (i < length1 - length2) {
curr1.val = list1.get(i)+curr1.val;
} else {
curr1.val = list1.get(i) + list2.get(i-(length1 - length2))+curr1.val;
}
if (curr1.next != null) {
curr1.next.val = curr1.val / 10;
curr1.val = curr1.val % 10;
} else {
if (curr1.val >= 10) {
ListNode node = new ListNode(curr1.val / 10);
curr1.next = node;
curr1.val = curr1.val % 10;
}
}
curr1 = curr1.next;
}
return one;
} else {
ListNode two = curr2;
for (int i = 0; i < length2; i++) {
if (i == 0) {
curr2.val = 0;
}
if (i < length2 - length1) {
curr2.val = list2.get(i)+curr2.val;
} else {
curr2.val = list2.get(i) + list1.get(i-(length2 - length1))+curr2.val;
}
if (curr2.next != null) {
curr2.next.val = curr2.val / 10;
curr2.val = curr2.val % 10;
} else {
if (curr2.val >= 10) {
ListNode node = new ListNode(curr2.val / 10);
curr2.next = node;
curr2.val = curr2.val % 10;
}
}
curr2 = curr2.next;
}
return two;
}
}
// 两数之和 ok
public static ListNode addTwoNumbers2(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dummyHead;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummyHead.next;
}
//----------------------------------------------------------------------------------------------------------------------
static List<ListNode> getNodes(ListNode head) {
List<ListNode> list = new LinkedList<>();
StringBuffer stringBuffer = new StringBuffer();
while (head != null) {
list.add(head);
stringBuffer.append(head.val).append(",");
head = head.next;
}
System.out.println(stringBuffer.toString());
return list;
}
//----------------------------------------------------------------------------------------------------------------------
//876. 返回链表的中间节点 start----------------------
//1 把链表遍历到数组中,通过数组获取中间节点
public ListNode middleNode1(ListNode head) {
if (head == null) {
return null;
} else {
List<ListNode> list = new ArrayList<>();
while (head != null) {
list.add(head);
head = head.next;
}
return list.get(list.size() / 2);
}
}
//2 遍历一遍获取链表长度,下一次遍历到一半
public ListNode middleNode2(ListNode head) {
return null;
}
//3.双指针:一个slow = next,一个fast = next.next,当fast遍历结束时,slow正好在中间
public ListNode middleNode3(ListNode head) {
ListNode slow = head;
if (head == null) {
return null;
} else {
ListNode fast = head.next;
while (fast != null) {
slow = slow.next;
fast = fast.next;
if (fast == null) {
return slow;
} else {
fast = fast.next;
}
}
}
return slow;
}
//876. 返回链表的中间节点 end----------------------
//----------------------------------------------------------------------------------------------------------------------
//21 合并两个有序链表 start --------------
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
List<Integer> list = new LinkedList<>();
while (l1 != null) {
list.add(l1.val);
l1 = l1.next;
}
while (l2 != null) {
list.add(l2.val);
l2 = l2.next;
}
ListNode head = null;
ListNode now = null;
ListNode next;
for (Integer integer : list) {
if (head == null) {
head = new ListNode(integer);
now = head;
} else {
next = new ListNode(integer);
now.next = next;
}
}
return null;
}
//21 合并两个有序链表 end --------------------
//----------------------------------------------------------------------------------------------------------------------
//203 删除链表中等于给定值 val 的所有节点 start-----------------------
// ok
public static ListNode removeElements(ListNode head, int val) {
if (head == null) {
return null;
} else {
ListNode pre = new ListNode(0);
pre.next = head;
//创建一个首节点,处理原先的head节点被删除的情况
ListNode first = pre;
while (head != null) {
//定义一个指向next节点的指针
ListNode next = head.next;
//当前节点要删除
if (head.val == val) {
//将当前节点的next置为null
head.next = null;
//当前节点的前置节点的next指向当前节点的下一个节点
pre.next = next;
} else {
//如果不需要删除,就是更新当前节点和pre节点
pre = head;
}
head = next;
}
return first.next;
}
}
//203 移除链表元素 end-----------------------
//----------------------------------------------------------------------------------------------------------------------
//160 相交链表 找到两个单链表相交的起始节点。 start ------------------
// https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
public ListNode getIntersectionNode1(ListNode headA, ListNode headB) {
return null;
}
//2. A,B链表都走相交前面部分的A+B路程
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode pA = headA, pB = headB;
while (pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
//160 相交链表 end ------------------
//-------------------------------------------------------------------------------------------------------------------
//142. 环形链表 II 返回链表开始入环的第一个节点。 如果链表无环,则返回 null
// https://leetcode-cn.com/problems/linked-list-cycle-ii/
//1. 通过Set保存,第一次遇到重复的节点即入环的第一个节点 ok
public ListNode detectCycle(ListNode head) {
Set<ListNode> set = new HashSet<>();
while (head != null) {
if (set.contains(head)) {
return head;
}
set.add(head);
head = head.next;
}
return null;
}
//----------------------------------------------------------------------------------------------------------------------
//19. 删除链表的倒数第N个节点 start --------------
// https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/hua-jie-suan-fa-19-shan-chu-lian-biao-de-dao-shu-d/
//1. 遍历一遍获取链表长度, 第二遍遍历到length-n ok
public static ListNode removeNthFromEnd1(ListNode head, int n) {
if (head == null) {
return null;
} else {
ListNode first = head;
int length = 0;
while (head != null) {
length++;
head = head.next;
}
head = first;
if (length < n) {
return head;
} else if (length == n) {
return head.next;
} else {
for (int i = 1; i <= length - n; i++) {
if (i == length - n) {
//只遍历到倒数第二个节点,因此head.next不会为null
head.next = head.next.next;
return first;
} else {
head = head.next;
}
}
return first;
}
}
}
//2. 双指针: 第一个指针先移动到第n个元素,然后第二个指针一起移动,
// 当第一个指针移动到尾结点时,说明第一个指针就是倒数第n个节点 ok
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode pre = new ListNode(0);
pre.next = head;
ListNode start = pre, end = pre;
while (n != 0) {
start = start.next;
n--;
}
while (start.next != null) {
start = start.next;
end = end.next;
}
end.next = end.next.next;
return pre.next;
}
//3. my双指针:删除倒数第n个节点 ok
public static ListNode myremoveNthFromEnd3(ListNode head, int n) {
if (head == null) {
return null;
}
ListNode fast = null;
ListNode slow = null;
while (n > 0) {
if (fast == null) {
fast = head;
} else {
fast = fast.next;
}
//n大于链表长度
if (fast == null) {
return head;
}
n--;
}
while (fast != null) {
if (fast.next == null) {
//说明删除的是第一个节点
if (slow == null) {
return head.next;
}
//删除节点
ListNode next = slow.next;
slow.next = next.next;
return head;
} else {
//更新slow和fast
if (slow == null) {
slow = head;
} else {
slow = slow.next;
}
fast = fast.next;
}
}
//到这说明n<=0
return head;
}
//19. 删除链表的倒数第N个节点 end --------------
//----------------------------------------------------------------------------------------------------------------------
static class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
}