文章目录
仅仅是我之前看左神记的笔记,既然学到这里了,就整理下来吧
回头要自己重新写!!!巩固一下!!!
0. 单链表
单链表节点结构:
Class Node<v>{
V value;
Node nest
}
双向链表节点结构:
Class Node<V>{
V value;
Node nest;
Node last;
}
反转单向和双向链表(略)
打印两个有序链表的公共部分(略)
1. 题目:给定一个单链表的头节点head,请判断是不是回文结构
长度为N,时间复杂度为O(N,额外空间复杂度为O(1)
快慢指针+逆序
import java.util.Scanner;
class Node {
public int val;
public Node next;
Node(int val, Node next){
this.val = val;
this.next = next;
}
Node(){
}
}
public class Index2 {
// need 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;
n1.next = null;
Node n3 = null;
while(n2 != null){
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
}
n3 = n1;
n2 = head;
boolean res = true;
while(n1 != null && n2 != null){
if(n1.val != n2.val){
res = false;
break;
}
n1 = n1.next;
n2 = n2.next;
}
n1 = n3.next;
n3.next = null;
while(n1 != null){
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
// 创建链表
public static Node CreateNode(Node head){
Node q = head;
Scanner in = new Scanner(System.in);
int num = in.nextInt();
q.val = num;
q.next = null;
num = in.nextInt();
while(num != 0){
Node p = new Node(num, null);
q.next = p;
q = p;
num = in.nextInt();
}
return head;
}
// 输出链表
public static void printNode(Node head){
Node p = head;
while(p != null){
System.out.println(p.val);
p = p.next;
}
}
public static void main(String[] args) {
Node a = new Node();
a = CreateNode(a);
boolean res = isPalindrome3(a);
System.out.println(res);
}
}
2. 将单向链表按某值划分成左边大、中间相等、右边大的形式
时间复杂度请达到O(n),额外空间复杂度请达到O(1)
建立三对head和tail进行连接:
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;
// every node distribued to three lists
while(head != null){
next = head.next;
head.next = null;
if(head.val < pivot){
if(sH == null){
sH = head;
sT = head;
}else{
sT.next = head;
sT = head;
}
}else if(head.val == 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;
}
// small and equal reconnect
if(sT != null){
sT.next = eH;
eT = eT == null ? sT : eT;
}
if(eT != null){
eT.next = mH;
}
return sH != null ? sH:(eH != null? eH : mH);
}
3. 复制含有随机指针节点的链表
时间复杂度O(N),额外空间复杂度O(1)
使用哈希表:
// 复制随机链表
public static Node copyListWithRand1(Node head){
HashMap<Node, Node> map = new HashMap<Node, Node>();
Node cur = head;
while(cur != null){
map.put(cur, new Node(cur.val, null));
cur = cur.next;
}
cur = head;
while(cur != null){
map.get(cur).next = map.get(cur.next);
map.get(cur).rand = map.get(cur.rand);
cur = cur.next;
}
return map.get(head);
}
复制节点被指向:
public static Node copyListWithRand2(Node head){
if(head == null)
return null;
Node cur = head;
Node next = null;
while(cur != null){
next = cur.next;
cur.next = new Node(cur.val, null);
cur.next.next = next;
cur = next;
}
cur = head;
Node curCopy = null;
while(cur != null){
next = cur.next.next;
curCopy = cur.next;
curCopy.rand = cur.rand != null ? cur.rand.next : null;
cur = next;
}
Node res = head.next;
cur = head;
while(cur != null){
next = cur.next.next;
curCopy = cur.next;
cur.next = next;
curCopy.next = next != null ? next.next : null;
cur = next;
}
return res;
}
4. 判断链表有无环,有环则返回第一个环节点
// 快慢指针返回环的第一个节点
public static Node getLoopNode(Node head){
if(head == null || head.next == null || head.next.next == null)
return null;
Node n1 = head.next;
Node n2 = head.next.next;
while(n1 != n2){
if(n2.next == null || n2.next.next == null)
return null;
n2 = n2.next.next;
n1 = n1.next;
}
n2 = head;
while(n1 != n2){
n1 = n1.next;
n2 = n2.next;
}
return n1;
}
5. 两个链表都无环,返回第一个相交节点,不相交,返回null
// 两个有环链表,返回第一个相交节点,不相交返回null
public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2){
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 == loop1){
return loop1;
}
cur1 = cur1.next;
}
return null;
}
}
// 配套使用
public static Node getIntersectNode(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;
}