判断回文链表
import java.util.Stack;
/**
* 判断一个链表是否为回文结构
* 【题目】 给定一个链表的头节点head,请判断该链表是否为回文结构。
* 例如: 1->2->1,返回true。 1->2->2->1,返回true。
* 15->6->15,返回true。 1->2->3,返回false。
* 进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1)。
* @author Administrator
*
*/
public class Palindrome {
// need n extra space
public static boolean isPalindrome1(Node head){
if (head == null || head.next == null) {
return true;
}
Stack<Node> help = new Stack<>();
Node cur = head;
while(cur != null) {
help.push(cur);
cur = cur.next;
}
while(head != null) {
if(head.value != help.pop().value){
return false;
}
head = head.next;
}
return true;
}
/* need n/2 extra space
* 1.当快指针到达链表末尾(链表节点为偶数时,尾部位置是链表长度减一)时,
* 慢指针处在中间位置(节点为偶数时,是右边部分)
* 2.从慢指针所指位置开始,将节点依次压入栈中
* 3.比较值是否相等
*/
public static boolean isPalindrome2(Node head) {
if (head == null || head.next == null) {
return true;
}
Node right = head.next;
Node cur = head;
while(cur.next != null && cur.next.next != null) {
right = right.next;
cur = cur.next.next;
}
Stack<Node> help = new Stack<>();
while(right != null) {
help.push(right);
right = right.next;
}
while(!help.isEmpty()) {
if(head.value != help.pop().value) {
return false;
}
head = head.next;
}
return true;
}
/*
* need 0(1) extra space
* 1.慢指针指到中间位置时,将mid的next置为null,将mid->right部分的链表反转,
* 2.反转后即right->mid 跟 left->mid进行比较,
* 3.返回结果前将反转的链表反转回来
* */
public static boolean isPalindrome3(Node head) {
if(head == null || head.next == null) {
return true;
}
Node n1 = head; // 慢指针(偶数时,遍历之后在left part最后一个节点,奇数时,是mid)
Node n2 = head; // 快指针
while(n2.next != null && n2.next.next != null) {
n1 = n1.next; // n1 -> mid
n2 = n2.next.next; // n2 -> end
} // after while,n1 ->mid or left part last node
n2 = n1.next; // n2 -> right part first node
n1.next = null; // mid -> null
Node n3 = null;
while(n2 != null) { // reverse list
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
} // after while, n1 -> right part last node
n3 = n1; // n3 -> save last node
n2 = head; // n2 -> left part first node
boolean res = true;
while(n1 != null && n2 != null) {
if(n1.value != n2.value) {
res = false;
break;
}
n1 = n1.next; // left -> mid
n2 = n2.next; // right -> mid
}
n1 = n3.next;
n3.next = null;
while(n1 != null) { // reserve list
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
public static class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
public static void printLinkedList(Node head) {
System.out.println("LinkedList:");
while(head != null) {
System.out.print(head.value + " ");
head = head.next;
}
System.out.println();
}
// for test
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("=========================");
}
}
运行结果
LinkedList:
true | true | true |
LinkedList:
=========================
LinkedList:
1
true | true | true |
LinkedList:
1
=========================
LinkedList:
1 2
false | false | false |
LinkedList:
1 2
=========================
LinkedList:
1 1
true | true | true |
LinkedList:
1 1
=========================
LinkedList:
1 2 3
false | false | false |
LinkedList:
1 2 3
=========================
LinkedList:
1 2 1
true | true | true |
LinkedList:
1 2 1
=========================
LinkedList:
1 2 3 1
false | false | false |
LinkedList:
1 2 3 1
=========================
LinkedList:
1 2 2 1
true | true | true |
LinkedList:
1 2 2 1
=========================
LinkedList:
1 2 3 2 1
true | true | true |
LinkedList:
1 2 3 2 1
=========================
复制含有随机指针节点的链表
import java.util.HashMap;
import java.util.Map;
/**
* 复制含有随机指针节点的链表
* 【题目】 一种特殊的链表节点类描述如下:
public class Node {
public int value;
public Node next;
public Node rand;
public Node(int data) {
this.value = data;
}
}
* Node类中的value是节点值,next指针和正常单链表中next指针的意义一 样,都指向下一个节点,
* rand指针是Node类中新增的指针,这个指针可 能指向链表中的任意一个节点,也可能指向null。
* 给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个 函数完成这个链表中所有结构的复制,
* 并返回复制的新链表的头节点。
* 进阶:不使用额外的数据结构,只用有限几个变量,且在时间复杂度为 O(N)内完成原问题要实现的函数。
* @author Administrator
*
*/
public class Code10_CopyListWithRandom {
public static class Node {
public int value;
public Node next;
public Node rand;
public Node(int data) {
this.value = data;
}
}
// 使用哈希表
public static Node copyListWithRand1(Node head) {
Map<Node,Node> map = new HashMap<>();
Node cur = head;
while (cur != null) {
map.put(cur, new Node(cur.value));
cur = cur.next;
}
cur = head;
while (cur != null) {
map.get(cur).next = cur.next;
map.get(cur).rand = cur.rand;
cur = cur.next;
}
return map.get(head);
}
// 不使用哈希表
public static Node copyListWithRand2(Node head) {
if (head == null) {
return null;
}
// copy node and link to every node
Node cur = head;
Node next = null;
while (cur != null) {
next = cur.next;
cur.next = new Node(cur.value);
cur.next.next = next;
cur = next;
}
// set copy node random
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;
}
// split
Node res = head.next;
cur = head;
while (cur != null) {
next = cur.next.next;
curCopy = cur.next;
curCopy.next = next !=null ? next.next : null;
cur.next = next;
cur = next;
}
return res;
}
public static void printRandLinkedList(Node head) {
Node cur = head;
System.out.print("order: ");
while (cur != null) {
System.out.print(cur.value + " ");
cur = cur.next;
}
System.out.println();
cur = head;
System.out.print("rand: ");
while (cur != null) {
System.out.print(cur.rand == null ? "- " : cur.rand.value + " ");
cur = cur.next;
}
System.out.println();
}
public static void main(String[] args) {
Node head = null;
Node res1 = null;
Node res2 = null;
printRandLinkedList(head);
res1 = copyListWithRand1(head);
printRandLinkedList(res1);
res2 = copyListWithRand2(head);
printRandLinkedList(res2);
printRandLinkedList(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(4);
head.next.next.next.next = new Node(5);
head.next.next.next.next.next = new Node(6);
head.rand = head.next.next.next.next.next; // 1 -> 6
head.next.rand = head.next.next.next.next.next; // 2 -> 6
head.next.next.rand = head.next.next.next.next; // 3 -> 5
head.next.next.next.rand = head.next.next; // 4 -> 3
head.next.next.next.next.rand = null; // 5 -> null
head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4
printRandLinkedList(head);
res1 = copyListWithRand1(head);
printRandLinkedList(res1);
res2 = copyListWithRand2(head);
printRandLinkedList(res2);
printRandLinkedList(head);
System.out.println("=========================");
}
}
测试结果
order:
rand:
order:
rand:
order:
rand:
order:
rand:
=========================
order: 1 2 3 4 5 6
rand: 6 6 5 3 - 4
order: 1 2 3 4 5 6
rand: 6 6 5 3 - 4
order: 1 2 3 4 5 6
rand: 6 6 5 3 - 4
order: 1 2 3 4 5 6
rand: 6 6 5 3 - 4
=========================