class 3

  • 用数组结构实现大小固定的队列和栈
package com.godzuo.java;/*** @author quanquan* @create 2020-04-20-22:36*/
public class Array_To_Stack_Queue {public static class arrayToStack{private Integer[] arr;Integer size;public arrayToStack(int initSize){ //initSize为栈的长度if(initSize<0){throw new IllegalArgumentException("The init size is less than 0");}arr = new Integer[initSize];size = 0;}public void push(int obj){if (size == arr.length){throw  new ArrayIndexOutOfBoundsException("The stack is full");}arr[size++] = obj;}public Integer pop(int obj){if (size == 0){throw  new ArrayIndexOutOfBoundsException("The stack is empty");}return  arr[--size];}//显示栈顶元素,但不弹出public Integer peek() {if (size == 0) {return null;}return arr[size - 1];}}public static class ArrayQueue {private Integer[] arr;private Integer size;private Integer first;private Integer last;public ArrayQueue(int initSize) {if (initSize < 0) {throw new IllegalArgumentException("The init size is less than 0");}arr = new Integer[initSize];size = 0;first = 0;last = 0;}//显示队列头的元素,但不弹出public Integer peek() {if (size == 0) {return null;}return arr[first];}public void push(int obj) {if (size == arr.length) {throw new ArrayIndexOutOfBoundsException("The queue is full");}size++;arr[last] = obj;last = last == arr.length - 1 ? 0 : last + 1; //last到arr.length后返回0}public Integer poll() {if (size == 0) {throw new ArrayIndexOutOfBoundsException("The queue is empty");}size--;int tmp = first;first = first == arr.length - 1 ? 0 : first + 1;return arr[tmp];}}public static void main(String[] args) {}
}
  • 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
    【要求】
    1.pop、push、getMin操作的时间复杂度都是O(1)。
    2.设计的栈类型可以使用现成的栈结构。
package com.godzuo.java;import java.util.Stack;/*** 同时实现两个栈,一个正常操作,另一个如果当前数小则压入当前数,否则压入栈顶元素,两个栈同时压出* @author quanquan* @create 2020-04-21-10:45*/
public class GetMinStack {private Stack<Integer> stackData;private Stack<Integer> stackMin;public GetMinStack(){this.stackData = new Stack<Integer>();this.stackMin = new Stack<Integer>();}public void push(int i){if (stackMin.isEmpty()){stackMin.push(i);}else if (i<stackMin.peek()){stackMin.push(i);}else{stackMin.push(stackMin.peek());}stackData.push(i);}public int pop(){if (stackData.isEmpty()){System.out.println("empty!");}else{stackData.pop();}return stackMin.pop();}public int getMin(){if (stackData.isEmpty()){System.out.println("empty!");}return stackMin.peek();}public static void main(String[] args) {GetMinStack stack1 = new GetMinStack();stack1.push(3);stack1.push(4);stack1.push(1);stack1.push(5);stack1.push(2);System.out.println(stack1.getMin());stack1.pop();stack1.pop();stack1.pop();System.out.println(stack1.getMin());}
}
  • 如何仅用队列结构实现栈结构? – 用两个队列实现栈
    如何仅用栈结构实现队列结构?-- 用两个栈结构
package com.godzuo.java;import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;/*** @author quanquan* @create 2020-04-21-15:40*/
public class TwoQueuesStack {private Queue<Integer> queue;private Queue<Integer> help;public TwoQueuesStack(){queue = new LinkedList<Integer>();help = new LinkedList<Integer>();}public void push(int i){queue.add(i);}public  int pop(){if (queue.isEmpty()){System.out.println("empty!");}while (queue.size()>1){help.add(queue.poll());}int res = queue.poll();swapStack();return res;}public int peek(){if (queue.isEmpty()){System.out.println("empty!");}while (queue.size()>1){help.add(queue.poll());}int res = queue.peek();help.add(queue.poll());swapStack();return res;}public void swapStack(){Queue<Integer> temp = queue;queue = help;help = temp;}public static void main(String[] args) {TwoQueuesStack queue = new TwoQueuesStack();queue.push(1);queue.push(2);queue.push(3);queue.push(4);System.out.println(queue.pop());System.out.println(queue.pop());System.out.println(queue.peek());System.out.println(queue.pop());System.out.println(queue.pop());}
}

DAY4

  • 猫狗队列

    宠物、狗和猫的类如下:
    public class Pet {

    private String type;

    public Pet(String type) { this.type = type; }

    public String getPetType() { return this.type; }

    }
    public class Dog extends Pet { public Dog() { super(“dog”); } }
    public class Cat extends Pet { public Cat() { super(“cat”); } }
    实现一种狗猫队列的结构,要求如下: 用户可以调用add方法将cat类或dog类的实例放入队列中; 用户可以调用pollAll方法,将队列中所有的实例按照进队列的先后顺序依次弹出; 用户可以调用pollDog方法,将队列中dog类的实例按照进队列的先后顺序依次弹出; 用户可以调用pollCat方法,将队列中cat类的实
    例按照进队列的先后顺序依次弹出; 用户可以调用isEmpty方法,检查队列中是否还有dog或cat的实例; 用户可以调用isDogEmpty方法,检查队列中是否有dog类的实例; 用户可以调用isCatEmpty方法,检查队列中是否有cat类的实例。

package com.godzuo.java;import java.util.LinkedList;
import java.util.Queue;public class DogCatQueues {public static class Pet {private String type;public Pet(String type) {this.type = type;}public String getPetType() {return this.type;}}public static class Dog extends Pet {public Dog() {super("dog");}}public static class Cat extends Pet {public Cat() {super("cat");}}//创建新类,增加count参数,用来记录每条数据存入的时间public static class PetEnterQueue {private Pet pet;private long count;public PetEnterQueue(Pet pet, long count) {this.pet = pet;this.count = count;}public Pet getPet() {return this.pet;}public long getCount() {return this.count;}public String getEnterPetType() {return this.pet.getPetType();}}public static class DogCatQueue {private Queue<PetEnterQueue> dogQ;private Queue<PetEnterQueue> catQ;private long count;public DogCatQueue() {this.dogQ = new LinkedList<PetEnterQueue>();this.catQ = new LinkedList<PetEnterQueue>();this.count = 0;}public void add(Pet pet) {if (pet.getPetType().equals("dog")) {this.dogQ.add(new PetEnterQueue(pet, this.count++));} else if (pet.getPetType().equals("cat")) {this.catQ.add(new PetEnterQueue(pet, this.count++));} else {throw new RuntimeException("err, not dog or cat");}}public Pet pollAll() {if (!this.dogQ.isEmpty() && !this.catQ.isEmpty()) {if (this.dogQ.peek().getCount() < this.catQ.peek().getCount()) {return this.dogQ.poll().getPet();} else {return this.catQ.poll().getPet();}} else if (!this.dogQ.isEmpty()) {return this.dogQ.poll().getPet();} else if (!this.catQ.isEmpty()) {return this.catQ.poll().getPet();} else {throw new RuntimeException("err, queue is empty!");}}public Dog pollDog() {if (!this.isDogQueueEmpty()) {return (Dog) this.dogQ.poll().getPet();} else {throw new RuntimeException("Dog queue is empty!");}}public Cat pollCat() {if (!this.isCatQueueEmpty()) {return (Cat) this.catQ.poll().getPet();} elsethrow new RuntimeException("Cat queue is empty!");}public boolean isEmpty() {return this.dogQ.isEmpty() && this.catQ.isEmpty();}public boolean isDogQueueEmpty() {return this.dogQ.isEmpty();}public boolean isCatQueueEmpty() {return this.catQ.isEmpty();}}public static void main(String[] args) {DogCatQueue test = new DogCatQueue();Pet dog1 = new Dog();Pet cat1 = new Cat();Pet dog2 = new Dog();Pet cat2 = new Cat();Pet dog3 = new Dog();Pet cat3 = new Cat();test.add(dog1);test.add(cat1);test.add(dog2);test.add(cat2);test.add(dog3);test.add(cat3);test.add(dog1);test.add(cat1);test.add(dog2);test.add(cat2);test.add(dog3);test.add(cat3);test.add(dog1);test.add(cat1);test.add(dog2);test.add(cat2);test.add(dog3);test.add(cat3);while (!test.isDogQueueEmpty()) {System.out.println(test.pollDog().getPetType());}while (!test.isEmpty()) {System.out.println(test.pollAll().getPetType());}}}
  • 转圈打印矩阵

    【题目】 给定一个整型矩阵matrix,请按照转圈的方式打印它。
    例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 1415 16 打印结果为:1,2,3,4,8,12,16,15,14,13,9,
    5,6,7,11, 10
    【要求】 额外空间复杂度为O(1)

package com.godzuo.java;/*** @author quanquan* @create 2020-04-21-21:56*/
public class PrintMatrixSpiralOrder {public static void spiralOrderPrint(int[][] matrix){int a = 0;int b = 0;int c = matrix.length-1;int d = matrix[0].length-1;while (a<=c && b<=d){printEdge(matrix,a++,b++,c--,d--);}}//旋转打印一圈public static void printEdge(int[][] m, int tR, int tC, int dR, int dC){if (tR == dR) {for (int i = tC; i <= dC; i++) {System.out.print(m[tR][i] + " ");}} else if (tC == dC) {for (int i = tR; i <= dR; i++) {System.out.print(m[i][tC] + " ");}}else{int curC = tC;int curR = tR;while (curC != dC) {System.out.print(m[tR][curC] + " ");curC++;}while (curR != dR) {System.out.print(m[curR][dC] + " ");curR++;}while (curC != tC) {System.out.print(m[dR][curC] + " ");curC--;}while (curR != tR) {System.out.print(m[curR][tC] + " ");curR--;}}}public static void main(String[] args) {int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },{ 13, 14, 15, 16 } };spiralOrderPrint(matrix);}
}
  • 旋转正方形矩阵
    【题目】 给定一个整型正方形矩阵matrix,请把该矩阵调整成
    顺时针旋转90度的样子。
    【要求】 额外空间复杂度为O(1)
package com.godzuo.java;public class RotateMatrix {public static void rotate(int[][] matrix) {int tR = 0;int tC = 0;int dR = matrix.length - 1;int dC = matrix[0].length - 1;while (tR < dR) {rotateEdge(matrix, tR++, tC++, dR--, dC--);}}public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) {int times = dC - tC; int tmp = 0;for (int i = 0; i != times; i++) {tmp = m[tR][tC + i];m[tR][tC + i] = m[dR - i][tC];m[dR - i][tC] = m[dR][dC - i];m[dR][dC - i] = m[tR + i][dC];m[tR + i][dC] = tmp;}}public static void printMatrix(int[][] matrix) {for (int i = 0; i != matrix.length; i++) {for (int j = 0; j != matrix[0].length; j++) {System.out.print(matrix[i][j] + " ");}System.out.println();}}public static void main(String[] args) {int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },{ 13, 14, 15, 16 } };printMatrix(matrix);rotate(matrix);System.out.println("=========");printMatrix(matrix);}}
  • 反转单向和双向链表
    【题目】 分别实现反转单向链表和反转双向链表的函数。
    【要求】 如果链表长度为N,时间复杂度要求为O(N),额外空间复杂度要求为O(1)

package com.godzuo.java;public class ReverseList {public static class Node {public int value;public Node next;public Node(int data) {this.value = data;}}public static Node reverseList(Node head) {Node pre = null;Node next = null;while (head != null) {//head为当前节点next = head.next; //保留当前节点的下一个节点值head.next = pre; //当前节点指向前节点,第一个节点指向空pre = head; //前节点向后移head = next; //当前节点向后移}return pre;}public static class DoubleNode {public int value;public DoubleNode last;public DoubleNode next;public DoubleNode(int data) {this.value = data;}}public static DoubleNode reverseList(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 void printLinkedList(Node head) {System.out.print("Linked List: ");while (head != null) {System.out.print(head.value + " ");head = head.next;}System.out.println();}public static void printDoubleLinkedList(DoubleNode head) {System.out.print("Double Linked List: ");DoubleNode end = null;while (head != null) {System.out.print(head.value + " ");end = head;head = head.next;}System.out.print("| ");while (end != null) {System.out.print(end.value + " ");end = end.last;}System.out.println();}public static void main(String[] args) {Node head1 = new Node(1);head1.next = new Node(2);head1.next.next = new Node(3);printLinkedList(head1);head1 = reverseList(head1);printLinkedList(head1);DoubleNode head2 = new DoubleNode(1);head2.next = new DoubleNode(2);head2.next.last = head2;head2.next.next = new DoubleNode(3);head2.next.next.last = head2.next;head2.next.next.next = new DoubleNode(4);head2.next.next.next.last = head2.next.next;printDoubleLinkedList(head2);printDoubleLinkedList(reverseList(head2));}
}
  • “之”字形打印矩阵
    【题目】 给定一个矩阵matrix,按照“之”字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12
    “之”字形打印的结果为:1,2,5,9,6,3,4,7,10,11,8,12
    【要求】 额外空间复杂度为O(1)
package com.godzuo.java;public class ZigZagPrintMatrix {public static void printMatrixZigZag(int[][] matrix) {int tR = 0;int tC = 0;int dR = 0;int dC = 0;int endR = matrix.length - 1;int endC = matrix[0].length - 1;boolean fromUp = false;while (tR != endR + 1) {    //或者dC != endC + 1printLevel(matrix, tR, tC, dR, dC, fromUp);tR = tC == endC ? tR + 1 : tR;tC = tC == endC ? tC : tC + 1;dC = dR == endR ? dC + 1 : dC;dR = dR == endR ? dR : dR + 1;fromUp = !fromUp;}System.out.println();}public static void printLevel(int[][] m, int tR, int tC, int dR, int dC,boolean f) {if (f) {while (tR != dR + 1) {System.out.print(m[tR++][tC--] + " ");//从右上打印到左下}} else {while (dR != tR - 1) {System.out.print(m[dR--][dC++] + " ");//从左下打印到右上}}}public static void main(String[] args) {int[][] matrix = { { 1, 2, 3}, { 4, 5, 6}, { 7, 8, 9,}, { 10, 11, 12 }};printMatrixZigZag(matrix);}}
  • 在行列都排好序的矩阵中找数
    【题目】 给定一个有N*M的整型矩阵matrix和一个整数K,matrix的每一行和每一 列都是排好序的。实现一个函数,判断K是否在matrix中。 例如: 0 1 2 5 ,2 3 4 7 ,4 4 4 8 ,5 7 7 9 如果K为7,返回true;如果K为6,返回false。
    【要求】 时间复杂度为O(N+M),额外空间复杂度为O(1)

    【答】从右上角开始,当前数比k大向左移,当前数比k小向右移

    ​ 或从左下角开始,当前数比k小向右,当前数比k大向上

    public static boolean isContains(int[][] matrix, int K) {int row = 0;int col = matrix[0].length - 1;while (row < matrix.length && col > -1) {if (matrix[row][col] == K) {return true;} else if (matrix[row][col] > K) {col--;} else {row++;}}return false;}
  • 打印两个有序链表的公共部分
    【题目】 给定两个有序链表的头指针head1和head2,打印两个链表的公共部分
   public static class Node{private int value;private Node next;public Node(int value){this.value = value;}}public static void printCommonPart(Node head1, Node head2){while (head1 != null && head2 != null){if (head1.value<head2.value){head1 = head1.next;}else if(head1.value>head2.value){head2 = head2.next;}else {System.out.print(head1.value+" ");head1 = head1.next;head2 = head2.next;}}System.out.println();}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();}
  • 链表问题

    在笔试过程中不用考虑额外空间复杂度,进来快的写出答案;面试时应该考虑额外空间复杂度最低,同时保证时间复杂度维持在O(N)

  • 判断一个链表是否为回文结构

    进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1)

package com.godzuo.java;import java.util.Stack;/*** @author quanquan* @create 2020-04-22-17:02*/
public class IsPalindromeList {public static class Node{private int value;private Node next;public Node(int value){this.value = value;}}// 需要O(N)额外空间复杂度public static boolean isPalindrome1(Node head) {Stack<Node> stack = new Stack<>();Node cur = head;while (cur != null) {stack.push(cur);cur = cur.next;}while (head != null) {if (head.value != stack.pop().value) {return false;}head = head.next;}return true;}//需要O(1)额外空间复杂度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) { // find mid noden1 = n1.next; // n1 -> midn2 = n2.next.next; // n2 -> end}n2 = n1.next; // n2 -> right part first noden1.next = null; // mid.next -> nullNode n3 = null;while (n2 != null) { // right part convertn3 = n2.next; // n3 -> save next noden2.next = n1; // next of right node convertn1 = n2; // n1 moven2 = n3; // n2 move}n3 = n1; // n3 -> save last noden2 = head;// n2 -> left first nodeboolean res = true;while (n1 != null && n2 != null) { // check palindromeif (n1.value != n2.value) {res = false;break;}n1 = n1.next; // left to midn2 = n2.next; // right to mid}n1 = n3.next;n3.next = null;while (n1 != null) { // 恢复链表n2 = n1.next;n1.next = n3;n3 = n1;n1 = n2;}return res;}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();}public static void main(String[] args) {Node head = null;printLinkedList(head);System.out.print(isPalindrome1(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.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.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.println(isPalindrome3(head) + " | ");printLinkedList(head);System.out.println("=========================");}}
  • 将单向链表按某值划分成左边小、中间相等、右边大的形式
    【题目】 给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值大于 pivot的节点。除这个要求外,对调整后的节点顺序没有更多的要求。 例如:链表9->0->4->5->1,pivot=3。调整后链表可以是1->0->4->9->5,也可以是0->1->9->5->4。总之,满足左部分都是小于3的节点,中间部分都是等于3的节点(本例中这个部分为空),右部分都是大于3的节点即可。对某部分内部的节点顺序不做要求。
    【进阶】 在原问题的要求之上再增加如下两个要求。在左、中、右三个部分的内部也做顺序要求,要求每部分里的节点从左到右的顺序与原链表中节点的先后次序一致。 例如:链表9->0->4->5->1,pivot=3。
    调整后的链表是0->1->9->4->5。 在满足原问题要求的同时,左部分节点从左到右为0、1。在原链表中也是先出现0,后出现1;中间部分在本例中为空,不再讨论;右部分节点从左到右为9、4、5。在原链表中也是先出现9,然后出现4,最后出现5。
    如果链表长度为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)。
package com.godzuo.java;/*** @author quanquan* @create 2020-04-22-22:45*/
public class SmallerEqualBigger {public static class Node{private int value;private Node next;public Node(int num){this.value = num;}}//方法一:新建一个nodeArr数组,将原数组中的节点根据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;}//方法二:时间复杂度达O(N),额外空间复杂度O(1),且具有稳定性public static Node listPartition2(Node head,int pivot){Node sH = null; // small headNode sT = null; // small tailNode eH = null; // equal headNode eT = null; // equal tailNode bH = null; // big headNode bT = null; // big tailNode next = null; // save next node// every node distributed to three listswhile (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 reconnectif(sT != null){sT.next = eH;eT = eT == null ? sT : eT;}// all reconnectif (eT != null) {eT.next = bH;}return sH != null ? sH : eH != null ? eH : bH;}public static  void printLinkedList(Node node){System.out.println("Linked list:");while (node != null){System.out.print(node.value + " ");node = node.next;}System.out.println();}public static void main(String[] args) {Node head1 = new Node(7);head1.next = new Node(9);head1.next.next = new Node(1);head1.next.next.next = new Node(8);head1.next.next.next.next = new Node(5);head1.next.next.next.next.next = new Node(2);head1.next.next.next.next.next.next = new Node(5);printLinkedList(head1);//head1 = listPartition1(head1, 4);head1 = listPartition2(head1, 5);printLinkedList(head1);}
}

DAY5

  • 复制含有随机指针节点的链表
    【题目】 一种特殊的链表节点类描述如下:
    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)
    内完成原问题要实现的函数。
package com.godzuo.java;import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import java.util.HashMap;/*** @author quanquan* @create 2020-04-23-14:18*/
public class CopyListWithRandom {public static class Node{private int value;private Node next;private Node rand;public Node(int num){this.value = num;}}//利用HashMap,额外空间复杂度O(N)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.value));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);}//不利用HashMap,额外空间复杂度O(1)public static Node copyListWithRand2(Node head){if (head == null){return null;}Node cur = head;Node next = null;//copy node and link to every nodewhile (cur != null){next = cur.next;cur.next = new Node(cur.value);cur.next.next = next;cur = next;}cur = head;Node curCopy = null;// set copy node randwhile (cur != null){next = cur.next.next;curCopy = cur.next;curCopy.rand = cur.rand != null ? cur.rand : null;cur = next;}Node res = head.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 -> 6head.next.rand = head.next.next.next.next.next; // 2 -> 6head.next.next.rand = head.next.next.next.next; // 3 -> 5head.next.next.next.rand = head.next.next; // 4 -> 3head.next.next.next.next.rand = null; // 5 -> nullhead.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4printRandLinkedList(head);res1 = copyListWithRand1(head);printRandLinkedList(res1);res2 = copyListWithRand2(head);printRandLinkedList(res2);printRandLinkedList(head);System.out.println("=========================");}
}
  • 两个单链表相交的一系列问题
    【题目】 在本题中,单链表可能有环,也可能无环。给定两个单链表的头节点 head1和head2,这两个链表可能相交,也可能不相交。请实现一个函数, 如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null 即可。 要求:如果链表1的长度为N,链表2的长度为M,时间复杂度请达到 O(N+M),额外空间复杂度请达到O(1)。
package com.godzuo.java;/*** @author quanquan* @create 2020-04-23-21:36*/
public class FindFirstIntersectNode {public static class Node{private int value;private Node next;public Node(int data){this.value = data;}}//额外空间复杂度O(1),如果使用HashSet额外空间复杂度O(N),但会简单一点public static Node getIntersectNode(Node head1,Node head2){if (head1 == null || head2 == null){return null;}Node loop1 = getLoopNode(head1); //得到链表1的第一个入环节点Node loop2 = getLoopNode(head2); //得到链表2的第一个入环节点if (loop1 == null && loop2 == null){return noLoop(head1,head2); //两个无环链表的相交问题}if (loop1 != null && loop2 != null){return bothLoop(head1,loop1,head2,loop2); //两个有环链表的相交问题}return null;}public static Node getLoopNode(Node head){if (head == null || head.next == null || head.next.next == null){return null;}Node n1 = head.next; // n1 -> slow 快指针一次走两步Node n2 = head.next.next; // n2 -> fast 慢指针一次走一步while (n1 != n2){if (n2.next == null || n2.next.next == null){return  null;}n2 = n2.next.next;n1 = n1.next;}n2 = head; // n2 -> walk again from head 相遇后快指针回到开头while (n1 != n2){n1 = n1.next;n2 = n2.next;}return n1;}//两个无环链表的相交问题public static Node noLoop(Node head1, Node head2){if (head1 == null || head2 == null){return null;}Node cur1 = head1;Node cur2 = head2;int n = 0; //两个链表长度的差值while (cur1.next != null){n++;cur1 = cur1.next;}while (cur2.next != null){n--;cur2 = cur2.next;}if(cur1 != cur2){ //最后一个节点不相等,不可能相交return null;}cur1 = n > 0 ? head1 : head2;cur2 = cur1 == head1 ? head2 :head1;n = Math.abs(n);while (n != 0){cur1 = cur1.next;n--;}while (cur1 != cur2){cur1 = cur1.next;cur2 = cur2.next;}return cur1;}//两个有环链表的相交问题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 { //判断链表的环上有没有链表2cur1 = loop1.next;while (cur1 != loop1) {if (cur1 == loop2) {return loop1;}cur1 = cur1.next;}return null;}}public static void main(String[] args) {// 1->2->3->4->5->6->7->nullNode head1 = new Node(1);head1.next = new Node(2);head1.next.next = new Node(3);head1.next.next.next = new Node(4);head1.next.next.next.next = new Node(5);head1.next.next.next.next.next = new Node(6);head1.next.next.next.next.next.next = new Node(7);// 0->9->8->6->7->nullNode head2 = new Node(0);head2.next = new Node(9);head2.next.next = new Node(8);head2.next.next.next = head1.next.next.next.next.next; // 8->6System.out.println(getIntersectNode(head1, head2).value);// 1->2->3->4->5->6->7->4...head1 = new Node(1);head1.next = new Node(2);head1.next.next = new Node(3);head1.next.next.next = new Node(4);head1.next.next.next.next = new Node(5);head1.next.next.next.next.next = new Node(6);head1.next.next.next.next.next.next = new Node(7);head1.next.next.next.next.next.next = head1.next.next.next; // 7->4// 0->9->8->2...head2 = new Node(0);head2.next = new Node(9);head2.next.next = new Node(8);head2.next.next.next = head1.next; // 8->2System.out.println(getIntersectNode(head1, head2).value);// 0->9->8->6->4->5->6..head2 = new Node(0);head2.next = new Node(9);head2.next.next = new Node(8);head2.next.next.next = head1.next.next.next.next.next; // 8->4System.out.println(getIntersectNode(head1, head2).value);}
}
  • 二分的小扩展
    【题目】
    定义局部最小的概念。arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]是局部最小;如果arr[N-1]<arr[N-2],那么arr[N-1]是局部最小;如果0<i<N-1,既有arr[i]<arr[i-1],又有arr[i]<arr[i+1],那么arr[i]是局部最小。给定无序数组arr,已知arr中任意两个相邻的数都不相等。写一个函数,只需返回arr中任意一个局部最小出现的位置即可。
    在我们的印象中,当需要在一个数组中查找一个值的时候,如果这个数组是有序的情况下,我们是可以考虑使用二分法的,但是这个题目,给定一个无序的数组,其实也可以使用二分,谁说了有序才能二分呢?其实只要能确定一边有值就可以使用二分了。
package com.godzuo.java;public class FindOneLessValueIndex {public static int getLessIndex(int[] arr) {if (arr == null || arr.length == 0) {return -1; // no exist}//先解决最前和最后两个if (arr.length == 1 || arr[0] < arr[1]) {return 0;}if (arr[arr.length - 1] < arr[arr.length - 2]) {return arr.length - 1;}//然后中间部分使用二分int left = 1;int right = arr.length - 2;int mid = 0;while (left < right) {mid = (left + right) / 2;if (arr[mid] > arr[mid - 1]) {right = mid - 1;} else if (arr[mid] > arr[mid + 1]) {left = mid + 1;} else {return mid;}}return left;}public static void printArray(int[] arr) {for (int i = 0; i != arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}public static void main(String[] args) {int[] arr = { 6, 5, 3, 4, 6, 7, 8 };printArray(arr);int index = getLessIndex(arr);System.out.println("index: " + index + ", value: " + arr[index]);}
}

class3 队列、栈和链表(左程云左神算法 初级笔记 2018)相关推荐

  1. class4 二叉树(左程云左神算法 初级笔记 2018)

    class 4 DAY6 实现二叉树的先序.中序.后序遍历,包括递归方式和非递归方式 package com.godzuo.java;import java.util.Stack;/*** @auth ...

  2. 左程云牛客算法初级班笔记

    第一课 第二课 第三课 第四课 第五课 第六课 第七课 第八课 个人的上课笔记 记录了一些算法题细节的理解要点 第一课 估计递归大小复杂度的通式 a子过程样本量 b子过程发生了多少次 0: 除去子过程 ...

  3. 左程云算法课—02课程笔记

    目录 一.剖析递归行为和递归行为时间复杂度的估算 master公式的使用(满足子问题等规模) 二.归并排序 归并排序的扩展 小和问题 逆序对问题 三.荷兰国旗问题 问题一 问题二 四.快速排序 不改进 ...

  4. 数据结构与算法XS班-左程云第八节课笔记(归并排序和快速排序)

    第8节 归并排序和快速排序 ##这是数据结构与算法新手班-左程云第八节课的笔记## 归并排序 归并排序实际上是一个很经典的排序方法,时间复杂度o(N*logN). 递归版本(图解排序算法(四)之归并排 ...

  5. 数据结构与算法XS班-左程云第一节课笔记(位运算、算法是什么、简单排序)

    第1节 位运算.算法是什么.简单排序 ##这是数据结构与算法新手班-左程云第一节课的笔记## 1. 位运算 // 你们会不会表示一个数字的32位啊? // Java中int类型默认以32位二进制数在计 ...

  6. 左程云算法笔记(四)哈希表和有序表的使用、链表

    左程云算法笔记(四) 哈希表的使用 有序表的使用 链表 单链表反转 (LC206) 双向链表反转 打印两个有序链表的公共部分 合并两个有序链表(LC21) 判断一个链表是否为回文结构 (LC234) ...

  7. 【左程云Java算法】Chapter1-5:用一个栈实现另一个栈的排序

    [左程云Java算法]Chapter1-5:用一个栈实现另一个栈的排序 [题目] 用一个栈实现另一个栈的排序 [要求] 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个 ...

  8. 一周刷爆LeetCode,算法da神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记

    一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记 教程与代码地址 P1 出圈了!讲课之外我们来聊聊 ...

  9. 一看“左程云:200道算法与数据结构”,二刷“阿里云:70+算法题、30种大厂笔试高频知识点”,3月过去终于挺进我梦中的字节!

    不管是学生还是已经工作的人,我想彼此都有一个相同的梦想:进大厂! 眼看着2020年还有个三十来天就要完美收尾了,那么如何才能在未来三个月弯道超车赶上"金三银四的春招",进入梦寐以求 ...

最新文章

  1. 人类的思维方式有哪些?【达克效应】
  2. 用node实现websocket协议
  3. znet zbus 子项目
  4. 4.Windows下安装ZooKeeper
  5. python同时兼容2和3的几个技巧
  6. matlab广泛用于什么,目前,Matlab已成为世界上最受欢迎的科学和工程计算软件工具....
  7. 2.数据结构笔记学习--线性表基本操作
  8. linux命令行聊天,Linux 下使用talk 进行聊天
  9. asp.net 获取全部在线用户_Qamp;A | 在线考试问卷答疑
  10. vue——路由独有的生命周期函数 activated deactivated
  11. 水晶报表横向打印BUG处理
  12. vue+nodejs 将canvas发布到dlna投屏服务
  13. 汇编指令-adr与ldr伪汇编区别(8)
  14. C++11 列表初始化
  15. centos 修改root密码_Liunx 下安装数据库以及修改密码
  16. java 1.6 32位_JDK1.6 32位官方下载
  17. WFDB工具箱在Matlab2010b及更高版本上的安装
  18. 2014年360广告算法面试经历
  19. 2.8 STM32_按键扫描_安富莱
  20. Downloads Help 下载帮助

热门文章

  1. 2019-6-15-WPF-触摸到事件
  2. 如何去掉裁剪图片的边框_裁剪框
  3. 推荐一款智能化地理信息融合服务器
  4. 2022 年数字化转型火热,工业互联网的发展趋势怎么样?
  5. iphone7以及7P的模拟器删除应用解决办法
  6. 在霍格沃兹学习测试是种怎样的体验?
  7. Container启动
  8. 瓦片经纬度及行列号转换_Slippy map tilenames(瓦片和经纬度换算)
  9. DB2中编目本机当中数据库的方法
  10. Unity-BattleStar丨6. 动画系统-让BattleStar游戏中的角色动起来