链表没什么特别重要的算法,主要是了解该结构的Coding问题即可,下面直接上代码
package day004;
import java.util.Stack;
public class LinkList<T> {
// 节点类,单指针
class Node {
private T data;
private Node next;
public Node(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
//节点类,双指针
class DoubleNode {
public T value;
public DoubleNode last;
public DoubleNode next;
public DoubleNode(T data) {
this.value = data;
}
}
private Node head; //头节点
public Node getHead() {
return head;
}
//头插法
public LinkList<T> addFirst(T data) {
Node node = new Node(data);
if (this.head != null) {
node.next = this.head; //如果链表不为空,将头节点插入新来的节点后面
}
this.head = node; //更新头节点
return this;
}
//尾插法
public LinkList<T> addLast(T data) {
Node node = new Node(data);
Node cur = this.head;
if (this.head == null)
this.head = node;
else { //找到链表最后一个节点并插入
while (cur.next != null)
cur = cur.next;
cur.next = node;
}
return this;
}
public void clear() {
while (this.head != null) {
Node cur = this.head.next;
this.head.next = null;
this.head = cur;
}
}
//尾插,一整个数组
public LinkList<T> add(T[] data) {
for (T datum : data) {
this.addLast(datum);
}
return this;
}
@Override
public String toString() {
Node cur = head;
String str = "";
while (cur != null) {
str = (str + " " + cur.getData());
cur = cur.next;
}
return "LinkList{" +
str + "}";
}
//判断一个链表是否是回文结构
//思路1:准备一个栈,遍历链表,每个元素都压入栈中,然后在次遍历,链表走一个,栈中弹出一个,比较是否相等,如果都相等则是回文结构
public boolean isPalindrome1(Node head) {
Stack<Node> stack = new Stack<>();
Node cur = head;
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
cur = head;
while (cur != null) {
if (cur.data != stack.pop().getData()) {
return false;
}
cur = cur.next;
}
return true;
}
//思路二: 节省一半的空间,快慢指针,快指针一次走两个,慢指针走一个,快指针走完,慢指针来到中点位置,然后只需要将后面的一半入栈,然后和前面的一半比较是否相等即可
public 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> stack = new Stack<>();
while (right != null) {
stack.push(right);
right = right.next;
}
cur = head;
while (!stack.isEmpty()) {
if (cur.data != stack.pop().getData())
return false;
cur = cur.next;
}
return true;
}
//最省空间的思路
public 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.data!=n2.data) {
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;
}
}
package day004;
import day001.Utils;
import java.util.Arrays;
public class LinkListTest {
public static LinkList<Integer> list = new LinkList<>();
public static void test1(){
int[] arr = Utils.getArray(10,0,100);
list.add(Arrays.stream(arr).boxed().toArray(Integer[]::new)); //将int数组转为Integer数组
System.out.println(list);
}
public static void test2(){
Integer[] arr = {1};
System.out.println("测试回文 {1}:");
list.add(arr);
System.out.println(list.isPalindrome1(list.getHead()));
System.out.println(list.isPalindrome2(list.getHead()));
System.out.println(list.isPalindrome3(list.getHead()));
list.clear();
System.out.println("测试回文 {1,3,4,3,3,4,3,1}:");
Integer[] arr2 = {1,3,4,3,3,4,3,1};
list.add(arr2);
System.out.println(list.isPalindrome1(list.getHead()));
System.out.println(list.isPalindrome2(list.getHead()));
System.out.println(list.isPalindrome3(list.getHead()));
list.clear();
System.out.println("测试回文 {1,3,4,3,3,2,4,3,1}:");
Integer[] arr3 = {1,3,4,3,3,2,4,3,1};
list.add(arr3);
System.out.println(list.isPalindrome1(list.getHead()));
System.out.println(list.isPalindrome2(list.getHead()));
System.out.println(list.isPalindrome3(list.getHead()));
}
public static void main(String[] args) {
test2();
}
}
package day004;
public class ListPartition {
public static class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
//链表中的partition过程,大于某个值的放左边,等于某个值的放中间,大于某个值的放右边
public static Node listPartition1(Node head, int pivot) {
if (head == 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;
for (i = 0; i != nodeArr.length; i++) {
nodeArr[i] = cur;
cur = cur.next;
}
arrPartition(nodeArr, pivot);
for (i = 1; i != nodeArr.length; i++) {
nodeArr[i - 1].next = nodeArr[i];
}
nodeArr[i - 1].next = null;
return nodeArr[0];
}
public static void arrPartition(Node[] nodeArr, int pivot) {
int small = -1;
int big = nodeArr.length;
int index = 0;
while (index != big) {
if (nodeArr[index].value < pivot) {
swap(nodeArr, ++small, index++);
} else if (nodeArr[index].value == pivot) {
index++;
} else {
swap(nodeArr, --big, index);
}
}
}
public static void swap(Node[] nodeArr, int a, int b) {
Node tmp = nodeArr[a];
nodeArr[a] = nodeArr[b];
nodeArr[b] = tmp;
}
//思路2:准备6个指针,分别为小于区的头和尾,等于区域的头和尾,大于区域的头和尾,遍历链表,第一次看到大于小于等于num的数直接让头尾指针都指向它,第二次根据情况,头指针不变,尾指针指向新的尾,最后遍历完全后将小于区的尾连等于区的头,等于区的尾连大于区的头
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 bH = null; // big head
Node bT = 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 (bH == null) {
bH = head;
bT = head;
} else {
bT.next = head;
bT = head;
}
}
head = next;
}
// small and equal reconnect
if (sT != null) {
sT.next = eH;
eT = eT == null ? sT : eT;
}
// all reconnect
if (eT != null) {
eT.next = bH;
}
return sH != null ? sH : eH != null ? eH : bH;
}
public static void printLinkedList(Node node) {
System.out.print("Linked List: ");
while (node != null) {
System.out.print(node.value + " ");
node = node.next;
}
System.out.println();
}
}