时间复杂度
1.链表逆序
package class04;import java.util.ArrayList;
import java.util.List;public class Code01_ReverseList {public static class Node {public int value;public Node next;public Node(int data) {value = data;}}public static class DoubleNode {public int value;public DoubleNode last;public DoubleNode next;public DoubleNode(int data) {value = data;}}public static Node reverseLinkedList(Node head) {Node pre = null;Node next = null;while (head != null) {next = head.next;head.next = pre;pre = head;head = next;}return pre;}public static DoubleNode reverseDoubleList(DoubleNode head) {DoubleNode pre = null;DoubleNode next = null;while (head != null) {next = head.next;head.next = pre;head.last = next;pre = head;head = next;}return pre;}public static Node testReverseLinkedList(Node head) {if (head == null) {return null;}ArrayList<Node> list = new ArrayList<>();while (head != null) {list.add(head);head = head.next;}list.get(0).next = null;int N = list.size();for (int i = 1; i < N; i++) {list.get(i).next = list.get(i - 1);}return list.get(N - 1);}public static DoubleNode testReverseDoubleList(DoubleNode head) {if (head == null) {return null;}ArrayList<DoubleNode> list = new ArrayList<>();while (head != null) {list.add(head);head = head.next;}list.get(0).next = null;DoubleNode pre = list.get(0);int N = list.size();for (int i = 1; i < N; i++) {DoubleNode cur = list.get(i);cur.last = null;cur.next = pre;pre.last = cur;pre = cur;}return list.get(N - 1);}// for testpublic static Node generateRandomLinkedList(int len, int value) {int size = (int) (Math.random() * (len + 1));if (size == 0) {return null;}size--;Node head = new Node((int) (Math.random() * (value + 1)));Node pre = head;while (size != 0) {Node cur = new Node((int) (Math.random() * (value + 1)));pre.next = cur;pre = cur;size--;}return head;}// for testpublic static DoubleNode generateRandomDoubleList(int len, int value) {int size = (int) (Math.random() * (len + 1));if (size == 0) {return null;}size--;DoubleNode head = new DoubleNode((int) (Math.random() * (value + 1)));DoubleNode pre = head;while (size != 0) {DoubleNode cur = new DoubleNode((int) (Math.random() * (value + 1)));pre.next = cur;cur.last = pre;pre = cur;size--;}return head;}// for testpublic static List<Integer> getLinkedListOriginOrder(Node head) {List<Integer> ans = new ArrayList<>();while (head != null) {ans.add(head.value);head = head.next;}return ans;}// for testpublic static boolean checkLinkedListReverse(List<Integer> origin, Node head) {for (int i = origin.size() - 1; i >= 0; i--) {if (!origin.get(i).equals(head.value)) {return false;}head = head.next;}return true;}// for testpublic static List<Integer> getDoubleListOriginOrder(DoubleNode head) {List<Integer> ans = new ArrayList<>();while (head != null) {ans.add(head.value);head = head.next;}return ans;}// for testpublic static boolean checkDoubleListReverse(List<Integer> origin, DoubleNode head) {DoubleNode end = null;for (int i = origin.size() - 1; i >= 0; i--) {if (!origin.get(i).equals(head.value)) {return false;}end = head;head = head.next;}for (int i = 0; i < origin.size(); i++) {if (!origin.get(i).equals(end.value)) {return false;}end = end.last;}return true;}public static void f(Node head) {head = head.next;}// for testpublic static void main(String[] args) {int len = 50;int value = 100;int testTime = 100000;System.out.println("test begin!");for (int i = 0; i < testTime; i++) {Node node1 = generateRandomLinkedList(len, value);List<Integer> list1 = getLinkedListOriginOrder(node1);node1 = reverseLinkedList(node1);if (!checkLinkedListReverse(list1, node1)) {System.out.println("Oops1!");}Node node2 = generateRandomLinkedList(len, value);List<Integer> list2 = getLinkedListOriginOrder(node2);node2 = testReverseLinkedList(node2);if (!checkLinkedListReverse(list2, node2)) {System.out.println("Oops2!");}DoubleNode node3 = generateRandomDoubleList(len, value);List<Integer> list3 = getDoubleListOriginOrder(node3);node3 = reverseDoubleList(node3);if (!checkDoubleListReverse(list3, node3)) {System.out.println("Oops3!");}DoubleNode node4 = generateRandomDoubleList(len, value);List<Integer> list4 = getDoubleListOriginOrder(node4);node4 = reverseDoubleList(node4);if (!checkDoubleListReverse(list4, node4)) {System.out.println("Oops4!");}}System.out.println("test finish!");}}
2.单链表实现堆区跟队列
package class04;import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;public class Code02_LinkedListToQueueAndStack {public static class Node<V> {public V value;public Node<V> next;public Node(V v) {value = v;next = null;}}public static class MyQueue<V> {private Node<V> head;private Node<V> tail;private int size;public MyQueue() {head = null;tail = null;size = 0;}public boolean isEmpty() {return size == 0;}public int size() {return size;}public void offer(V value) {Node<V> cur = new Node<V>(value);if (tail == null) {head = cur;tail = cur;} else {tail.next = cur;tail = cur;}size++;}// C/C++的同学需要做节点析构的工作public V poll() {V ans = null;if (head != null) {ans = head.value;head = head.next;size--;}if (head == null) {tail = null;}return ans;}// C/C++的同学需要做节点析构的工作public V peek() {V ans = null;if (head != null) {ans = head.value;}return ans;}}public static class MyStack<V> {private Node<V> head;private int size;public MyStack() {head = null;size = 0;}public boolean isEmpty() {return size == 0;}public int size() {return size;}public void push(V value) {Node<V> cur = new Node<>(value);if (head == null) {head = cur;} else {cur.next = head;head = cur;}size++;}public V pop() {V ans = null;if (head != null) {ans = head.value;head = head.next;size--;}return ans;}public V peek() {return head != null ? head.value : null;}}public static void testQueue() {MyQueue<Integer> myQueue = new MyQueue<>();Queue<Integer> test = new LinkedList<>();int testTime = 5000000;int maxValue = 200000000;System.out.println("测试开始!");for (int i = 0; i < testTime; i++) {if (myQueue.isEmpty() != test.isEmpty()) {System.out.println("Oops!");}if (myQueue.size() != test.size()) {System.out.println("Oops!");}double decide = Math.random();if (decide < 0.33) {int num = (int) (Math.random() * maxValue);myQueue.offer(num);test.offer(num);} else if (decide < 0.66) {if (!myQueue.isEmpty()) {int num1 = myQueue.poll();int num2 = test.poll();if (num1 != num2) {System.out.println("Oops!");}}} else {if (!myQueue.isEmpty()) {int num1 = myQueue.peek();int num2 = test.peek();if (num1 != num2) {System.out.println("Oops!");}}}}if (myQueue.size() != test.size()) {System.out.println("Oops!");}while (!myQueue.isEmpty()) {int num1 = myQueue.poll();int num2 = test.poll();if (num1 != num2) {System.out.println("Oops!");}}System.out.println("测试结束!");}public static void testStack() {MyStack<Integer> myStack = new MyStack<>();Stack<Integer> test = new Stack<>();int testTime = 5000000;int maxValue = 200000000;System.out.println("测试开始!");for (int i = 0; i < testTime; i++) {if (myStack.isEmpty() != test.isEmpty()) {System.out.println("Oops!");}if (myStack.size() != test.size()) {System.out.println("Oops!");}double decide = Math.random();if (decide < 0.33) {int num = (int) (Math.random() * maxValue);myStack.push(num);test.push(num);} else if (decide < 0.66) {if (!myStack.isEmpty()) {int num1 = myStack.pop();int num2 = test.pop();if (num1 != num2) {System.out.println("Oops!");}}} else {if (!myStack.isEmpty()) {int num1 = myStack.peek();int num2 = test.peek();if (num1 != num2) {System.out.println("Oops!");}}}}if (myStack.size() != test.size()) {System.out.println("Oops!");}while (!myStack.isEmpty()) {int num1 = myStack.pop();int num2 = test.pop();if (num1 != num2) {System.out.println("Oops!");}}System.out.println("测试结束!");}public static void main(String[] args) {testQueue();testStack();}}
3.双链表结构实现双端队列
package class04;import java.util.Deque;
import java.util.LinkedList;public class Code03_DoubleLinkedListToDeque {public static class Node<V> {public V value;public Node<V> last;public Node<V> next;public Node(V v) {value = v;last = null;next = null;}}public static class MyDeque<V> {private Node<V> head;private Node<V> tail;private int size;public MyDeque() {head = null;tail = null;size = 0;}public boolean isEmpty() {return size == 0;}public int size() {return size;}public void pushHead(V value) { //从头部加Node<V> cur = new Node<>(value);if (head == null) { //之前没有节点,cur是第一个head = cur;tail = cur;} else {cur.next = head;head.last = cur;head = cur;}size++;}public void pushTail(V value) {Node<V> cur = new Node<>(value);if (head == null) {head = cur;tail = cur;} else {tail.next = cur;cur.last = tail;tail = cur;}size++;}public V pollHead() { //从头部弹出V ans = null;if (head == null) {return ans;}size--;ans = head.value;if (head == tail) { //只有一个节点head = null;tail = null;} else {head = head.next;head.last = null;}return ans;}public V pollTail() {V ans = null;if (head == null) {return ans;}size--;ans = tail.value;if (head == tail) {head = null;tail = null;} else {tail = tail.last;tail.next = null;}return ans;}public V peekHead() {V ans = null;if (head != null) {ans = head.value;}return ans;}public V peekTail() {V ans = null;if (tail != null) {ans = tail.value;}return ans;}}public static void testDeque() {MyDeque<Integer> myDeque = new MyDeque<>();Deque<Integer> test = new LinkedList<>();int testTime = 5000000;int maxValue = 200000000;System.out.println("测试开始!");for (int i = 0; i < testTime; i++) {if (myDeque.isEmpty() != test.isEmpty()) {System.out.println("Oops!");}if (myDeque.size() != test.size()) {System.out.println("Oops!");}double decide = Math.random();if (decide < 0.33) {int num = (int) (Math.random() * maxValue);if (Math.random() < 0.5) {myDeque.pushHead(num);test.addFirst(num);} else {myDeque.pushTail(num);test.addLast(num);}} else if (decide < 0.66) {if (!myDeque.isEmpty()) {int num1 = 0;int num2 = 0;if (Math.random() < 0.5) {num1 = myDeque.pollHead();num2 = test.pollFirst();} else {num1 = myDeque.pollTail();num2 = test.pollLast();}if (num1 != num2) {System.out.println("Oops!");}}} else {if (!myDeque.isEmpty()) {int num1 = 0;int num2 = 0;if (Math.random() < 0.5) {num1 = myDeque.peekHead();num2 = test.peekFirst();} else {num1 = myDeque.peekTail();num2 = test.peekLast();}if (num1 != num2) {System.out.println("Oops!");}}}}if (myDeque.size() != test.size()) {System.out.println("Oops!");}while (!myDeque.isEmpty()) {int num1 = myDeque.pollHead();int num2 = test.pollFirst();if (num1 != num2) {System.out.println("Oops!");}}System.out.println("测试结束!");}public static void main(String[] args) {testDeque();}}
4.k个节点的组内逆序调整
reverse函数
package class04;// 测试链接:https://leetcode.com/problems/reverse-nodes-in-k-group/
public class Code04_ReverseNodesInKGroup {// 不要提交这个类public static class ListNode {public int val;public ListNode next;}public static ListNode reverseKGroup(ListNode head, int k) {ListNode start = head;ListNode end = getKGroupEnd(start, k);if (end == null) { //第一组小于k个return head;}// 第一组凑齐了!head = end; //以后head不动了reverse(start, end);// 上一组的结尾节点ListNode lastEnd = start;while (lastEnd.next != null) {start = lastEnd.next;end = getKGroupEnd(start, k);if (end == null) {return head;}reverse(start, end);lastEnd.next = end;lastEnd = start;}return head;}//设一个函数,给你开始节点,数够k个,把第k个返回public static ListNode getKGroupEnd(ListNode start, int k) {while (--k != 0 && start != null) { //&前面--k!=0,指针往后走,&后面是不够k个返回空start = start.next; //}return start;}
//public static void reverse(ListNode start, ListNode end) {end = end.next; ListNode pre = null;ListNode cur = start;ListNode next = null;while (cur != end) { //到end才停,所以第一步end先往后跳一格next = cur.next;cur.next = pre;pre = cur;cur = next;}start.next = end;}}
5.两个链表相加
package class04;// 测试链接:https://leetcode.com/problems/add-two-numbers/
public class Code05_AddTwoNumbers {// 不要提交这个类public static class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val = val;}public ListNode(int val, ListNode next) {this.val = val;this.next = next;}}public static ListNode addTwoNumbers(ListNode head1, ListNode head2) {int len1 = listLength(head1);int len2 = listLength(head2);//长链表归l,短链表归sListNode l = len1 >= len2 ? head1 : head2;ListNode s = l == head1 ? head2 : head1;ListNode curL = l;ListNode curS = s;ListNode last = curL;int carry = 0; //单独开一个,储存进位信息(0/1)int curNum = 0;while (curS != null) { //第一阶段长链表短链表都有curNum = curL.val + curS.val + carry; //当前位置的值curL.val = (curNum % 10);carry = curNum / 10;last = curL; //last记录最后一个不空的节点(备份),直到第三阶段curL = curL.next;curS = curS.next;}while (curL != null) { 第二阶段,短链表没了curNum = curL.val + carry;curL.val = (curNum % 10);carry = curNum / 10;last = curL;curL = curL.next;}if (carry != 0) { 第二阶段,长短链表都没了last.next = new ListNode(1);}return l; //把两个链表相加之后的结果覆盖到原来的长链表中,也可以在单独开一个链表储存相加之后的额结果}// 求链表长度public static int listLength(ListNode head) {int len = 0;while (head != null) {len++;head = head.next;}return len;}}
6.两个有序链表的合并
package class04;// 测试链接:https://leetcode.com/problems/merge-two-sorted-lists
public class Code06_MergeTwoSortedLinkedList {// 不要提交这个类public static class ListNode {public int val;public ListNode next;}public static ListNode mergeTwoLists(ListNode head1, ListNode head2) {if (head1 == null || head2 == null) {return head1 == null ? head2 : head1;}ListNode head = head1.val <= head2.val ? head1 : head2; //小的做总头ListNode cur1 = head.next;ListNode cur2 = head == head1 ? head2 : head1;ListNode pre = head;while (cur1 != null && cur2 != null) {if (cur1.val <= cur2.val) {pre.next = cur1; //pre的指向,谁小指谁cur1 = cur1.next; //谁小谁往下走} else {pre.next = cur2;cur2 = cur2.next;}pre = pre.next;}pre.next = cur1 != null ? cur1 : cur2;return head;}}