第3节.pptx
1 单链表与双链表的简单练习
题目1:单链表和双链表如何反转
01 单链表反转

    //反转链表    public static ListNode reverseListNode(ListNode head) {        if (head == null || head.next == null) {            return head;        }        ListNode pre = null;        ListNode next = null;        while (head != null) {            next = head.next;            head.next = pre;            pre = head;            head = next;        }        return pre;    }    /*以下代码为对数器,测试单链表反转*/    //对数器,用List容器实现链表反转    public static ListNode comarator(ListNode head) {        if (head == null || head.next == null) {            return head;        }        List<ListNode> list = new ArrayList<>();        while (head != null) {            list.add(head);            head = head.next;        }        list.get(0).next = null;        for (int i = 1; i < list.size(); i++) {            list.get(i).next = list.get(i - 1);        }        return list.get(list.size() - 1);    }    //生成随机链表    public static ListNode generateRandomListNode(int listLength, int maxValue) {        ListNode cur = new ListNode(((int) (Math.random() * maxValue) - (int) (Math.random() * maxValue)), null);        //保证生成的链表至少有1个节点        ListNode head = cur;        int length = (int) (Math.random() * listLength + 1);        for (int i = 0; i < length - 1; i++) {            cur.next = new ListNode(((int) (Math.random() * maxValue) - (int) (Math.random() * maxValue)), null);            cur = cur.next;        }        return head;    }    检查两个链表结构是否一致    public static boolean check(ListNode head1, ListNode head2) {        if (head1 == null && head2 == null) {            return true;        }        if (head1 != null ^ head2 != null) {            return false;        }        while (head1 != null && head2 != null) {            if (head1.data != head2.data) {                return false;            }            head1 = head1.next;            head2 = head2.next;            if (head1 != null ^ head2 != null) {                return false;            }        }        return true;    }    //打印单链表    public static void printListNode(ListNode head) {        if (head == null) {            return;        }        while (head != null) {            System.out.print(head.data + " ");            head = head.next;        }        System.out.println();    }    //复制一个单链表结构    public static ListNode copyListNode(ListNode head) {        if (head == null) {            return head;        }        ListNode ans = new ListNode(head.data, null);        ListNode cur = ans;        while (head.next != null) {            cur.next = new ListNode(head.next.data, null);            cur = cur.next;            head = head.next;        }        return ans;    }
02 双链表反转

 /*双链表反转*/    public static DoubleListNode reverseDoubleListNode(DoubleListNode head) {        if (head == null || head.next == null) {            return head;        }        DoubleListNode pre = null;        DoubleListNode next = null;        while (head != null) {            next = head.next;            head.next = pre;            head.prev = next;            pre = head;            head = next;        }        return pre;    }    /*以下代码为对数器,用于测试*/    public static DoubleListNode comparator(DoubleListNode head) {        if (head == null || (head.next == null && head.prev == null)) {            return head;        }        List<DoubleListNode> list = new ArrayList<>();        while (head != null) {            list.add(head);            head = head.next;        }        list.get(0).next = null;        list.get(0).prev = list.get(1);        for (int i = 1; i < list.size(); i++) {            list.get(i).next = list.get(i - 1);            if (i == list.size() - 1) {                list.get(i).prev = null;            } else {                list.get(i).prev = list.get(i + 1);            }        }        return list.get(list.size() - 1);    }    public static DoubleListNode generateRandomDoubleListNode(int maxLength, int maxValue) {        //保证至少有一个节点        int length = (int) (Math.random() * maxLength + 1);        DoubleListNode head = new DoubleListNode((int) (Math.random() * maxValue + 1) - (int) (Math.random() * maxValue + 1), null, null);        DoubleListNode cur = head;        for (int i = 0; i < length - 1; i++) {            DoubleListNode next = new DoubleListNode((int) (Math.random() * maxValue + 1) - (int) (Math.random() * maxValue + 1), null, null);            cur.next = next;            next.prev = cur;            cur = next;        }        return head;    }    public static DoubleListNode copyDoubleListNode(DoubleListNode head) {        if (head == null) {            return null;        }        DoubleListNode ans = new DoubleListNode(head.data, null, null);        DoubleListNode cur = ans;        while (head.next != null) {            DoubleListNode next = new DoubleListNode(head.next.data, null, null);            cur.next = next;            next.prev = cur;            cur = next;            head = head.next;        }        return ans;    }    public static boolean check(DoubleListNode head1, DoubleListNode head2) {        if (head1 == null && head2 == null) {            return true;        }        if (head1 != null ^ head2 != null) {            return false;        }        DoubleListNode end1 = null;        DoubleListNode end2 = null;        //正向比较        while (head1 != null && head2 != null) {            if (head1.data != head1.data) {                return false;            }            end1 = head1;            end2 = head2;            head1 = head1.next;            head2 = head2.next;            if (head1 != null ^ head2 != null) {                return false;            }        }        //逆向比较        while (end1 != null && end2 != null) {            if (end1.data != end1.data) {                return false;            }            end1 = end1.prev;            end2 = end2.prev;            if (end1 != null ^ end2 != null) {                return false;            }        }        return true;    }    public static void printDoubleListNode(DoubleListNode head) {        if (head == null) {            return;        }        DoubleListNode end = null;        while (head != null) {            System.out.print(head.data+" ");            end = head;            head = head.next;        }        System.out.println();        while (end != null) {            System.out.print(end.data+" ");            end = end.prev;        }        System.out.println();    }
题目2:把给定值都删除
 /*把给定值都删除
     */
    public static ListNode deleteGivenValue(ListNode head, int value) {
        while (head != null && head.data == value) {
            head = head.next;
        }
        if (head == null) {
            return null;
        }
        ListNode cur = head;
        ListNode next = cur.next;
        while (next != null) {
            cur.next = null;
            if (next.data != value) {
                cur.next = next;
                cur = next;
            }
            next = next.next;
        }
        return head;
    }
    /*以下为对数器,用于测试*/
    public static ListNode comparator(ListNode head, int value) {
        if (head == null) {
            return null;
        }
        LinkedList<Integer> list = new LinkedList<>();
        while (head != null) {
            list.add(Integer.valueOf(head.data));
            head = head.next;
        }
        int count = 0;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) == value) {
                count++;
            }
        }
        for (int i = 0; i < count; i++) {
            list.remove(Integer.valueOf(value));
        }
        if (list.size() == 0) {
            return null;
        }
        head = new ListNode(list.get(0));
        ListNode cur = head;
        for (int i = 1; i < list.size(); i++) {
            ListNode next = new ListNode(list.get(i));
            cur.next = next;
            cur = next;
        }
        return head;
    }
    public static ListNode generateRandomListNode(int maxLength, int maxValue, int value) {
        int length = (int) (Math.random() * (maxLength + 1));
        if (length == 0) {
            return null;
        }
        ListNode head = new ListNode((int) (Math.random() * maxValue + 1) - (int) (Math.random() * maxValue + 1));
        ListNode cur = head;
        for (int i = 0; i < length - 1; i++) {
            double random = Math.random();
            ListNode next = null;
            if (random < 0.5) {
                next = new ListNode((int) (Math.random() * maxValue + 1));
            } else {
                next = new ListNode(value);
            }
            cur.next = next;
            cur = next;
        }
        return head;
    }
    public static boolean check(ListNode head1, ListNode head2) {
        if (head1 == null && head2 == null) {
            return true;
        }
        if (head1 != null ^ head2 != null) {
            return false;
        }
        while (head1 != null && head2 != null) {
            if (head1.data != head2.data) {
                return false;
            }
            head1 = head1.next;
            head2 = head2.next;
            if (head1 != null ^ head2 != null) {
                return false;
            }
        }
        return true;
    }
    public static ListNode copyListNode(ListNode head) {
        if (head == null) {
            return head;
        }
        ListNode ans = new ListNode(head.data);
        ListNode cur = ans;
        while (head.next != null) {
            cur.next = new ListNode(head.next.data);
            cur = cur.next;
            head = head.next;
        }
        return ans;
    }
    public static void printListNode(ListNode head) {
        if (head == null) {
            return;
        }
        while (head != null) {
            System.out.print(head.data + " ");
            head = head.next;
        }
        System.out.println();
    }
2 栈和队列
题目1:双链表实现栈和队列
01 双链表实现栈
 static class DoubleListNode<T> {
        public T data;
        public DoubleListNode<T> prev;
        public DoubleListNode<T> next;
        public DoubleListNode(T data) {
            this.data = data;
        }
    }
    static class MyStack<T> {
        private DoubleListNode<T> head;
        public MyStack() {
        }
        //push
        public void push(T num) {
            if (head == null) {
                head = new DoubleListNode<>(num);
            } else {
                DoubleListNode next = new DoubleListNode<>(num);
                head.next = next;
                next.prev = head;
                head = next;
            }
        }
        //pop
        public T pop() {
            if (head == null) {
                return null;
            }
            T data = head.data;
            head = head.prev;
            return data;
        }
        //isEmpty
        public boolean isEmpty() {
            return head == null;
        }
    }
02 双链表实现队列
 static class MyDeque<T> {
        DoubleListNode<T> head;
        DoubleListNode<T> end;
        public MyDeque() {
        }
        public void addFirst(T num) {
            DoubleListNode<T> cur = new DoubleListNode(num);
            if (head == null) {
                head = cur;
                end = cur;
            } else {
                cur.next = head;
                head.prev = cur;
                head = cur;
            }
        }
        public void addLast(T num) {
            DoubleListNode<T> cur = new DoubleListNode(num);
            if (head == null) {
                head = cur;
                end = head;
            } else {
                cur.prev = end;
                end.next = cur;
                end = cur;
            }
        }
        public T popFirst() {
            if (head == null) {
                return null;
            }
            T data = head.data;
            if (head == end) {
                head = null;
                end = null;
            } else {
                head = head.next;
                head.prev = null;
            }
            return data;
        }
        public T popLast() {
            if (end == null) {
                return null;
            }
            T data = end.data;
            if (end == head) {
                end = null;
                head = null;
            } else {
                end = end.prev;
                end.next = null;
            }
            return data;
        }
        public boolean isEmpty() {
            return head == null && end == null;
        }
    }
题目2:数组实现栈和队列
01 数组实现栈
 static class MyStack {
        private int[] arr;
        private static final int DEAUFAL_LENGTH = 16;
        private static int endIndex;
        private static int length;
        public MyStack() {
        }
        public void push(int num) {
            if (arr == null) {
                arr = new int[DEAUFAL_LENGTH];
                length = arr.length;
                endIndex = 0;
                arr[endIndex++] = num;
            } else {
                if (endIndex == length) {
                    length = length + (length >> 1);
                    int[] newArr = new int[length];
                    System.arraycopy(arr, 0, newArr, 0, arr.length);
                    arr = newArr;
                }
                arr[endIndex++] = num;
            }
        }
        public Integer pop() {
            if (arr == null && endIndex == 0) {
                return null;
            }
            return arr[--endIndex];
        }
        public boolean isEmpty() {
            return endIndex == 0;
        }
    }
02 数组实现队列
     /**
     * 数组实现队列
     */
    static class MyQueue {
        private final int[] arr;
        private final int length;
        private int size;
        private int pushIndex;
        private int popIndex;
        private MyQueue(int length) {
            this.length = length;
            arr = new int[length];
            pushIndex = 0;
            popIndex = 0;
        }
        public static MyQueue getQueue(int length) {
            return new MyQueue(length);
        }
        public void push(int num) throws RuntimeException {
            if (size == length) {
                throw new RuntimeException("队列已满,添加失败");
            }
            arr[pushIndex] = num;
            size++;
            pushIndex = nextIndex(pushIndex);
        }
        public Integer pop() throws RuntimeException {
            if (size == 0) {
                return null;
            }
            int ans = arr[popIndex];
            popIndex = nextIndex(popIndex);
            size--;
            return ans;
        }
        public boolean isEmpty() {
            return size == 0;
        }
        private int nextIndex(int index) {
            return index < length - 1 ? index + 1 : 0;
        }
    }
题目3:实现一个特殊的栈,在基本功能的基础上,再实现返回栈中最小元素的功能
   /*
        * 实现一个特殊的栈,在基本功能的基础上,再实现返回栈中最小元素的功能
        1)pop、push、getMin操作的时间复杂度都是 O(1)。
        2)设计的栈类型可以使用现成的栈结构。
        */
    static class MyStack {
        private Stack<Integer> stack;
        private Stack<Integer> minValueStack;
        private int minValue;
        public MyStack() {
            stack = new Stack<>();
            minValueStack = new Stack<>();
        }
        public void push(int num) {
            if (minValueStack.isEmpty()) {
                minValue = num;
            } else {
                minValue = minValueStack.peek() < num ? minValueStack.peek() : num;
            }
            stack.push(num);
            minValueStack.push(minValue);
        }
        public Integer pop() {
            if (stack.isEmpty()) {
                return null;
            }
            minValueStack.pop();
            return stack.pop();
        }
        public Integer getMin() {
            if (minValueStack.isEmpty()) {
                return null;
            }
            return minValueStack.peek();
        }
        public boolean isEmpty(){
            return stack.isEmpty();
        }
    }
题目4:用栈结构实现队列
 //如何用栈结构实现队列结构
    static class MyQueue {
        private Stack<Integer> pushStack;
        private Stack<Integer> popStack;
        public MyQueue() {
            pushStack = new Stack<>();
            popStack = new Stack<>();
        }
        public void add(int num) {
            pushStack.push(num);
        }
        public Integer poll() {
            if (popStack.empty() && pushStack.empty()) {
                return null;
            }
            pushStackPollToPopStack();
            return popStack.pop();
        }
        public Integer peek() {
            if (popStack.empty() && pushStack.empty()) {
                return null;
            }
            pushStackPollToPopStack();
            return popStack.peek();
        }
        public boolean isEmpty() {
            return pushStack.isEmpty() && popStack.isEmpty();
        }
        private void pushStackPollToPopStack() {
            if (popStack.empty()) {
                while (!pushStack.empty()) {
                    popStack.push(pushStack.pop());
                }
            }
        }
    }
题目5:用队列结构实现栈
    static class MyStack {
        private Queue<Integer> pushQueue;
        private Queue<Integer> popQueue;
        public MyStack() {
            pushQueue = new LinkedList<>();
            popQueue = new LinkedList<>();
        }
        public void push(int num) {
            pushQueue.add(num);
        }
        public Integer pop() {
            while (pushQueue.size() > 1) {
                popQueue.add(pushQueue.poll());
            }
            Integer ans = pushQueue.poll();
            Queue<Integer> temp = pushQueue;
            pushQueue = popQueue;
            popQueue = temp;
            return ans;
        }
        public Integer peek() {
            while (pushQueue.size() > 1) {
                popQueue.add(pushQueue.poll());
            }
            Integer ans = pushQueue.poll();
            popQueue.add(ans);
            Queue<Integer> temp = pushQueue;
            pushQueue = popQueue;
            popQueue = temp;
            return ans;
        }
        public boolean isEmpty() {
            return pushQueue.isEmpty();
        }
    }
3 递归时间复杂度估算
