快慢指针
public class LinkedListMid {
public static class Node{
public int value;
public Node next;
public Node(int value){
this.value = value;
}
}
//输入链表头节点,奇数长度返回中点,偶数长度返回上中点
//快慢指针实现
public static Node midOrUpMidNode(Node head){
if (head == null || head.next == null || head.next.next == null){
return head;
}
Node slow = head.next;
Node fast = head.next.next;
while (fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//输入链表头节点,奇数长度返回中点,偶数长度返回下中点
public static Node midOrDownMidNode(Node head){
if (head == null || head.next == null || head.next.next == null){
return head;
}
Node slow = head.next;
Node fast = head.next;
while (fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//输入链表头节点,奇数长度返回中点前一个,偶数长度返回上中点前一个
public static Node midOrUpMidPreNode(Node head){
if (head == null || head.next == null || head.next.next == null){
return null;
}
Node slow = head;
Node fast = head.next.next;
while (fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//输入链表头节点,奇数长度返回中点前一个,偶数长度返回下中点前一个
public static Node midOrDownMidPreNode(Node head){
if (head == null || head.next == null){
return null;
}
Node slow = head;
Node fast = head.next;
while (fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public static Node right1(Node head){
if (head == null){
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur!=null){
arr.add(cur);
cur = cur.next;
}
return arr.get((arr.size()-1)/2);
}
public static Node right2(Node head) {
if (head == null) {
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur != null) {
arr.add(cur);
cur = cur.next;
}
return arr.get(arr.size() / 2);
}
public static Node right3(Node head) {
if (head == null || head.next == null || head.next.next == null) {
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur != null) {
arr.add(cur);
cur = cur.next;
}
return arr.get((arr.size() - 3) / 2);
}
public static Node right4(Node head) {
if (head == null || head.next == null) {
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur != null) {
arr.add(cur);
cur = cur.next;
}
return arr.get((arr.size() - 2) / 2);
}
public static void main(String[] args) {
Node test = null;
test = new Node(0);
test.next = new Node(1);
test.next.next = new Node(2);
test.next.next.next = new Node(3);
test.next.next.next.next = new Node(4);
test.next.next.next.next.next = new Node(5);
test.next.next.next.next.next.next = new Node(6);
test.next.next.next.next.next.next.next = new Node(7);
test.next.next.next.next.next.next.next.next = new Node(8);
Node ans1 = null;
Node ans2 = null;
ans1 = midOrUpMidNode(test);
ans2 = right1(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
ans1 = midOrDownMidNode(test);
ans2 = right2(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
ans1 = midOrUpMidPreNode(test);
ans2 = right3(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
ans1 = midOrDownMidPreNode(test);
ans2 = right4(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
}
}
回文问题
import java.util.Stack;
public class IsPalindromeList {
public static class Node{
public int value;
public Node next;
public Node(int value){
this.value = value;
}
}
//判断链表是否属于回文
//need n extra space
public static boolean isPalindrome1(Node head){
if (head == null){
return true;
}
Stack<Node> stack = new Stack<>();
Node cur = head;
while (cur != null){
stack.push(cur);
cur = cur.next;
}
while (head != null){
if (head.value != stack.pop().value){
return false;
}
head = head.next;
}
return true;
}
//need n/2 extra space
//判断是否为回文
public static boolean isPalindrome2(Node head){
if (head == null || head.next == null){
return true;
}
Node rihgt = head.next;
Node cur = head;
while (cur.next != null && cur.next.next != null){
rihgt = rihgt.next;
cur = cur.next.next;
}
Stack<Node> stack = new Stack<>();
while (rihgt != null){
stack.push(rihgt);
rihgt = rihgt.next;
}
while (!stack.isEmpty()){
if (head.value != stack.pop().value){
return false;
}
head = head.next;
}
return true;
}
//need O(1) extra space
//回文
public static boolean isPalindrome3(Node head){
if (head == null || head.next == null){
return true;
}
//找到链表中点和终点
Node n1 = head;
Node n2 = head;
while (n2.next != null && n2.next.next != null){
n1 = n1.next;
n2 = n2.next.next;
}
//反转后半部分链表
n2 = n1.next; //n2-->right part first node
n1.next = null; // mid.next = null
Node n3 = null;
while (n2 != null){
n3 = n2.next; // n3-->save next node
n2.next = n1; // 反转
n1 = n2;
n2 = n3;
}
n3 = n1; //保存右边反转后头节点
n2 = head; //左边头节点
boolean res = true;
while (n1 != null && n2 != null){
if (n1.value != n2.value){
res = false;
break;
}
n1 = n1.next;
n2 = n2.next;
}
//将反转的链表再反转回来
n1 = null;
n2 = null;
while (n3 != null){
n1 = n3.next;
n3.next = n2;
n2 = n3;
n3 = n1;
}
return res;
}
//for test
public static void printLinkedList(Node head){
System.out.print("Linked list: ");
while (head != null){
System.out.print(head.value+" ");
head = head.next;
}
System.out.println();
}
public static void main(String[] args) {
Node head = null;
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(1);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(1);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(1);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(2);
head.next.next.next = new Node(1);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(2);
head.next.next.next.next = new Node(1);
printLinkedList(head);
System.out.print(isPalindrome1(head) + " | ");
System.out.print(isPalindrome2(head) + " | ");
System.out.println(isPalindrome3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
}
}
链表排序
import java.util.ArrayList;
public class SmallEqualBigger {
public static class Node{
public int value;
public Node next;
public Node(int value){
this.value = value;
}
}
public static Node listPartition1(Node head,int pivot){
if (head == null || head.next == null){
return head;
}
Node cur = head;
int i =0;
while (cur != null){
i++;
cur = cur.next;
}
Node[] nodeArr = new Node[i];
i=0;
cur = head;
while (cur != null){
nodeArr[i] = cur;
cur = cur.next;
i++;
}
arrPartition(nodeArr,pivot);
for (i=1;i != nodeArr.length;i++){
nodeArr[i-1].next = nodeArr[i];
}
nodeArr[i-1].next = null;
return nodeArr[0];
}
private static void arrPartition(Node[] nodeArr, int pivot) {
int small = -1;
int big = nodeArr.length;
int index = 0;
while (index!=big){
if (nodeArr[index] !=null && nodeArr[index].value < pivot){
swap(nodeArr,index++,++small);
}else if (nodeArr[index]!= null &&nodeArr[index].value == pivot){
index++;
}else {
swap(nodeArr,index,--big);
}
}
}
private static void swap(Node[] nodeArr, int i, int i1) {
Node tmp = nodeArr[i];
nodeArr[i] = nodeArr[i1];
nodeArr[i1] = tmp;
}
//分成小、中、大三部分,再把各个部分之间串起来
public static Node listPartition2(Node head,int pivot){
Node sH = null; //small head
Node sT = null; //small tail
Node eH = null; //equal head
Node eT = null; //equal tail
Node mH = null; //big head
Node mT = null; //big tail
Node next = null; //save next node
//every node distributed to three lists
while (head != null){
next = head.next;
head.next = null;
if (head.value < pivot){
if (sH == null){
sH = head;
sT = head;
}else {
sT.next = head;
sT = head;
}
}else if (head.value == pivot){
if (eH == null){
eH = head;
eT = head;
}else {
eT.next = head;
eT = head;
}
}else {
if (mH == null){
mH = head;
mT = head;
}else {
mT.next = head;
mT = head;
}
}
head = next;
}
//小于区的尾巴连等于区的头。等于区的尾巴连大于去的头
if (sT != null){
sT.next = eH;
eT = eT == null ? sT : eT; //下一步,谁去连大于区的头谁就取eT
}
// 下一步,一定是需要用eT 去接 大于区域的头
// 有等于区域,eT -> 等于区域的尾结点
// 无等于区域,eT -> 小于区域的尾结点
// eT 尽量不为空的尾巴节点
if (eT != null){
eT.next = mH;
}
return sH != null ? sH : (eH != null ? eH : mH);
}
public static void printLinkedList(Node head){
System.out.print("Linked list: ");
while (head != null){
System.out.print(head.value+" ");
head = head.next;
}
System.out.println();
}
public static void main(String[] args) {
Node head1 = new Node(7);
head1.next = new Node(9);
head1.next.next = new Node(1);
head1.next.next.next = new Node(8);
head1.next.next.next.next = new Node(5);
head1.next.next.next.next.next = new Node(2);
head1.next.next.next.next.next.next = new Node(5);
printLinkedList(head1);
head1 = listPartition1(head1, 4);
//head1 = listPartition2(head1, 5);
printLinkedList(head1);
}
}
一种特殊链表
import java.util.HashMap;
public class CopyListWithRandom {
public static class Node{
public int val;
public Node next;
public Node random;
public Node(int value){
this.val = value;
this.next = null;
this.random = null;
}
}
//给定一个由Node节点类型组成的无环单链表的头节点 head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点。
public static Node copyRandomList1(Node head){
//key 老节点
//value 新节点
HashMap<Node, Node> map = new HashMap<>();
Node cur = head;
while (cur != null){
map.put(cur,new Node(cur.val));
cur = cur.next;
}
cur = head;
while (cur != null){
// cur 老
//map.get(cur) 新
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
cur = cur.next;
}
return map.get(head);
}
public static Node copyRandomList2(Node head){
if (head == null){
return null;
}
Node cur = head;
Node next = null;
// 1 -> 2 -> 3 -> null
// 1 -> 1' -> 2 -> 2' -> 3 -> 3'
while (cur != null){
next = cur.next;
cur.next = new Node(cur.val);
cur.next.next = next;
cur = next;
}
cur = head;
Node copy = null;
while (cur != null){
next = cur.next.next;
copy = cur.next;
copy.random = cur.random != null ? cur.random.next : null;
cur = next;
}
//在next方向上把新 老链分离
cur = head;
Node res = head.next;
while (cur != null){
next = cur.next.next;
copy = cur.next;
cur.next = next;
copy.next = next != null? next.next : null;
cur = next;
}
return res;
}
}
链表环
public class FindFirstIntersectNode {
//给定两个可能有环也可能无环的单链表,头节点head1和head2。请实现一个函数,如果两个链表相交,请返回相交的 第一个节点。如果不相交,返回null
//如果两个链表长度之和为N,时间复杂度请达到O(N),额外空间复杂度 请达到O(1)
public static class Node{
public int value;
public Node next;
public Node(int value){
this.value = value;
}
}
public static Node getInsertNode(Node head1,Node head2){
if (head1 == null || head2 == null){
return null;
}
Node loop1 = getLoopNode(head1);
Node loop2 = getLoopNode(head2);
if (loop1 == null && loop2 == null){
return noLoop(head1,head2);
}
if (loop1 != null && loop2 != null){
return bothLoop(head1,loop1,head2,loop2);
}
return null;
}
//找到链表的第一个入环节点,如果无环,返回null
public static Node getLoopNode(Node head){
if (head == null || head.next == null || head.next.next == null){
return null;
}
Node slow = head.next;
Node fast = head.next.next;
//追击问题,跑的快的在环里总会跟跑的慢的相遇,
while (slow != fast){
if (fast.next == null || fast.next.next == null){
return null;
}
slow = slow.next;
fast = fast.next.next;
}
fast = head;
//相遇后,跑的快的回到起点保持和慢一样的速度,相遇时就是环的节点
while (fast != slow){
slow = slow.next;
fast = fast.next;
}
return slow;
}
//如果两个链表都没环,返回第一个相交点, 如果不相交返回null
public static Node noLoop(Node head1,Node head2){
if (head1 == null || head2 == null){
return null;
}
Node cur1 = head1;
Node cur2 = head2;
int n=0;
while (cur1.next != null){
n++;
cur1 = cur1.next;
}
while (cur2.next != null){
n--;
cur2 = cur2.next;
}
if (cur1 != cur2){
return null;
}
// n -> head1 - head2 的长度的值
cur1 = n > 0 ? head1 : head2; //谁长,谁的头变成cur1
cur2 = cur1 == head1 ? head2 :head1; //短的链表头变成cur2
n = Math.abs(n);
while (n !=0){
n--;
cur1 = cur1 != null ? cur1.next : null;
}
//此时cur1、cur2两个链表长度一样
while (cur1 != cur2){
cur1 = cur1 != null ? cur1.next : null;
cur2= cur2 != null ? cur2.next : null;
}
return cur1;
}
//两个有环列表,相交返回第一个相交点,不相交返回null
public static Node bothLoop(Node head1,Node loop1,Node head2,Node loop2){
if (head1 == null || head2 == null){
return null;
}
Node cur1 = null;
Node cur2 = null;
//如果入环节点一样,相交必在入环前
if (loop1 == loop2){
cur1 = head1;
cur2 = head2;
int n = 0;
while (cur1 != loop1){
n++;
cur1 = cur1.next;
}
while (cur2 != loop2){
n--;
cur2 = cur2.next;
}
cur1 = n>0 ? head1:head2;
cur2 = cur1 == head1 ? head2 : head1;
n = Math.abs(n);
while (n!=0){
n--;
cur1 = cur1.next;
}
while (cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}else {
cur1 = loop1.next;
while (cur1 != loop1){
if (cur1 == loop2){
return loop1;
}
cur1 = cur1.next;
}
return null;
}
}
public static void main(String[] args) {
// 1->2->3->4->5->6->7->null
Node head1 = new Node(1);
head1.next = new Node(2);
head1.next.next = new Node(3);
head1.next.next.next = new Node(4);
head1.next.next.next.next = new Node(5);
head1.next.next.next.next.next = new Node(6);
head1.next.next.next.next.next.next = new Node(7);
// 0->9->8->6->7->null
Node head2 = new Node(0);
head2.next = new Node(9);
head2.next.next = new Node(8);
head2.next.next.next = head1.next.next.next.next.next; // 8->6
System.out.println(getInsertNode(head1, head2).value);
// 1->2->3->4->5->6->7->4...
head1 = new Node(1);
head1.next = new Node(2);
head1.next.next = new Node(3);
head1.next.next.next = new Node(4);
head1.next.next.next.next = new Node(5);
head1.next.next.next.next.next = new Node(6);
head1.next.next.next.next.next.next = new Node(7);
head1.next.next.next.next.next.next = head1.next.next.next; // 7->4
// 0->9->8->2...
head2 = new Node(0);
head2.next = new Node(9);
head2.next.next = new Node(8);
head2.next.next.next = head1.next; // 8->2
System.out.println(getInsertNode(head1, head2).value);
// 0->9->8->6->4->5->6..
head2 = new Node(0);
head2.next = new Node(9);
head2.next.next = new Node(8);
head2.next.next.next = head1.next.next.next.next.next; // 8->6
System.out.println(getInsertNode(head1, head2).value);
}
}
from —左程云算法基础课