├── CodeInterviewGuide ├── Chapter01_Stack&Queue │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ └── Q1009.md ├── Chapter02_List │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ ├── Q1009.md │ ├── Q1010.md │ ├── Q1011.md │ ├── Q1012.md │ ├── Q1013.md │ ├── Q1014.md │ ├── Q1015.md │ ├── Q1016.md │ ├── Q1017.md │ ├── Q1018.md │ ├── Q1019.md │ └── Q1020.md ├── Chapter03_BT │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ ├── Q1009.md │ ├── Q1010.md │ ├── Q1011.md │ ├── Q1012.md │ ├── Q1013.md │ ├── Q1014.md │ ├── Q1015.md │ ├── Q1016.md │ ├── Q1017.md │ ├── Q1018.md │ ├── Q1019.md │ ├── Q1020.md │ ├── Q1021.md │ ├── Q1022.md │ ├── Q1023.md │ └── Q1024.md ├── Chapter04_RecursionAndDP │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ ├── Q1009.md │ ├── Q1010.md │ ├── Q1011.md │ ├── Q1012.md │ ├── Q1013.md │ ├── Q1014.md │ ├── Q1015.md │ ├── Q1016.md │ └── Q1017.md ├── Chapter05_String │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ ├── Q1009.md │ ├── Q1010.md │ ├── Q1011.md │ ├── Q1012.md │ ├── Q1013.md │ ├── Q1014.md │ ├── Q1015.md │ ├── Q1016.md │ ├── Q1017.md │ ├── Q1018.md │ ├── Q1019.md │ ├── Q1020.md │ ├── Q1021.md │ ├── Q1022.md │ └── Q1023.md ├── Chapter06_Bit │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ └── Q1006.md ├── Chapter07_ArrayAndMatrix │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ ├── Q1009.md │ ├── Q1010.md │ ├── Q1011.md │ ├── Q1012.md │ ├── Q1013.md │ ├── Q1014.md │ ├── Q1015.md │ ├── Q1016.md │ ├── Q1017.md │ ├── Q1018.md │ ├── Q1019.md │ ├── Q1020.md │ ├── Q1021.md │ ├── Q1022.md │ ├── Q1023.md │ ├── Q1024.md │ ├── Q1025.md │ └── Q1026.md ├── Chapter08_Others │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ ├── Q1009.md │ ├── Q1010.md │ ├── Q1011.md │ ├── Q1012.md │ ├── Q1013.md │ ├── Q1014.md │ ├── Q1015.md │ ├── Q1016.md │ ├── Q1017.md │ ├── Q1018.md │ ├── Q1019.md │ ├── Q1020.md │ ├── Q1021.md │ ├── Q1022.md │ ├── Q1023.md │ ├── Q1024.md │ ├── Q1025.md │ ├── Q1026.md │ ├── Q1027.md │ ├── Q1028.md │ ├── Q1029.md │ ├── Q1030.md │ ├── Q1031.md │ ├── Q1032.md │ ├── Q1033.md │ └── Q1034.md └── README.md ├── INTERVIEW └── Interview.md ├── InternetRecruitingAlgorithmProblems ├── 360 │ └── Problem Description 2018.md ├── 58TC │ └── Problem Description 2018.md ├── ALiBaba │ └── Problem Description 2018.md ├── Baidu │ └── Problem Description 2018.md ├── DIDI │ └── Problem Description 2017.md ├── ENVISION │ └── Problem Description 2018.md ├── HUAWEI │ └── Problem Description 2018.md ├── IFLYTEK │ └── Problem Description 2018.md ├── JD │ ├── Problem Description 2017.md │ └── Problem Description 2018.md ├── MEITUAN │ ├── Problem Description 2017.md │ ├── Problem Description 2018.md │ └── pic │ │ └── Q2Y2017.png ├── MERCHANTSBANK │ └── Problem Description 2018.md ├── MI │ ├── Problem Description 2017.md │ └── Problem Description 2018.md ├── NETEASE │ ├── Problem Description 2017.md │ ├── Problem Description 2018.md │ └── pic │ │ ├── Q10Y2017.jpg │ │ ├── Q11Y2017.jpg │ │ ├── Q1Y2017.jpg │ │ ├── Q3Y2018.png │ │ └── Q7Y2017.jpg ├── PINDUODUO │ └── Problem Description 2018.md ├── QIY │ └── Problem Description 2018.md ├── Readme.md ├── TENCENT │ ├── Problem Description 2017.md │ └── Problem Description 2018.md ├── TOUTIAO │ └── Problem Description 2018.md └── YOUDAO │ └── Problem Description 2017.md ├── JianZhiOffer ├── Code │ ├── Q1001.md │ ├── Q1002.md │ ├── Q1003.md │ ├── Q1004.md │ ├── Q1005.md │ ├── Q1006.md │ ├── Q1007.md │ ├── Q1008.md │ ├── Q1009.md │ ├── Q1010.md │ ├── Q1011.md │ ├── Q1012.md │ ├── Q1013.md │ ├── Q1014.md │ ├── Q1015.md │ ├── Q1016.md │ ├── Q1017.md │ ├── Q1018.md │ ├── Q1019.md │ ├── Q1020.md │ ├── Q1021.md │ ├── Q1022.md │ ├── Q1023.md │ ├── Q1024.md │ ├── Q1025.md │ ├── Q1026.md │ ├── Q1027.md │ ├── Q1028.md │ ├── Q1029.md │ ├── Q1030.md │ ├── Q1031.md │ ├── Q1032.md │ ├── Q1033.md │ ├── Q1034.md │ ├── Q1035.md │ ├── Q1036.md │ ├── Q1037.md │ ├── Q1038.md │ ├── Q1039.md │ ├── Q1040.md │ ├── Q1041.md │ ├── Q1042.md │ ├── Q1043.md │ ├── Q1044.md │ ├── Q1045.md │ ├── Q1046.md │ ├── Q1047.md │ ├── Q1048.md │ ├── Q1049.md │ ├── Q1050.md │ ├── Q1051.md │ ├── Q1052.md │ ├── Q1053.md │ ├── Q1054.md │ ├── Q1055.md │ ├── Q1056.md │ ├── Q1057.md │ ├── Q1058.md │ ├── Q1059.md │ ├── Q1060.md │ ├── Q1061.md │ ├── Q1062.md │ ├── Q1063.md │ ├── Q1064.md │ ├── Q1065.md │ └── pic │ │ ├── Q1014P1.png │ │ ├── Q1015P1.png │ │ ├── Q1016P1.png │ │ ├── Q1017P1.png │ │ ├── Q1018P1.png │ │ ├── Q1020P1.png │ │ ├── Q1021P1.png │ │ ├── Q1023P1.png │ │ ├── Q1024P1.png │ │ ├── Q1024P2.png │ │ ├── Q1024P3.png │ │ ├── Q1025P1.png │ │ ├── Q1026P1.png │ │ ├── Q1027P1.png │ │ ├── Q1027P2.png │ │ ├── Q1028P1.png │ │ ├── Q1029P1.png │ │ ├── Q1029P2.png │ │ ├── Q1029P3.png │ │ ├── Q1030P1.png │ │ ├── Q1033P1.png │ │ ├── Q1033P2.png │ │ ├── Q1034P1.png │ │ ├── Q1035P1.png │ │ ├── Q1036P1.png │ │ ├── Q1037P1.png │ │ ├── Q1038P1.png │ │ ├── Q1039P1.png │ │ ├── Q1040P1.png │ │ ├── Q1041P1.png │ │ ├── Q1041P2.png │ │ ├── Q1042P1.png │ │ ├── Q1043P1.png │ │ ├── Q1044P1.png │ │ ├── Q1045P1.png │ │ ├── Q1045P2.png │ │ ├── Q1045P3.png │ │ ├── Q1047P1.png │ │ └── Q1047P2.png └── README.md ├── LICENSE └── Readme.md /CodeInterviewGuide/Chapter01_Stack&Queue/Q1002.md: -------------------------------------------------------------------------------- 1 | ## 由两个栈组成的队列 2 | 3 | **题目:** 4 | >编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek)。 5 | 6 | ```java 7 | import java.util.Stack; 8 | 9 | public class Problem_02_TwoStacksImplementQueue { 10 | 11 | public static class TwoStacksQueue { 12 | public Stack stackPush; 13 | public Stack stackPop; 14 | 15 | public TwoStacksQueue() { 16 | stackPush = new Stack(); 17 | stackPop = new Stack(); 18 | } 19 | 20 | public void add(int pushInt) { 21 | stackPush.push(pushInt); 22 | } 23 | 24 | public int poll() { 25 | if (stackPop.empty() && stackPush.empty()) { 26 | throw new RuntimeException("Queue is empty!"); 27 | } else if (stackPop.empty()) { 28 | while (!stackPush.empty()) { 29 | stackPop.push(stackPush.pop()); 30 | } 31 | } 32 | return stackPop.pop(); 33 | } 34 | 35 | public int peek() { 36 | if (stackPop.empty() && stackPush.empty()) { 37 | throw new RuntimeException("Queue is empty!"); 38 | } else if (stackPop.empty()) { 39 | while (!stackPush.empty()) { 40 | stackPop.push(stackPush.pop()); 41 | } 42 | } 43 | return stackPop.peek(); 44 | } 45 | } 46 | 47 | public static void main(String[] args) { 48 | TwoStacksQueue test = new TwoStacksQueue(); 49 | test.add(1); 50 | test.add(2); 51 | test.add(3); 52 | System.out.println(test.peek()); 53 | System.out.println(test.poll()); 54 | System.out.println(test.peek()); 55 | System.out.println(test.poll()); 56 | System.out.println(test.peek()); 57 | System.out.println(test.poll()); 58 | } 59 | 60 | } 61 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter01_Stack&Queue/Q1003.md: -------------------------------------------------------------------------------- 1 | ## 用递归函数和栈操作逆序一个栈 2 | 3 | **题目:** 4 | >一个栈依次压人1,2,3,4,5,那么从栈顶到栈底分别为5,4,3,2,1。将这个站转置后,从栈顶到栈底为1,2,3,4,5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。 5 | 6 | ```java 7 | import java.util.Stack; 8 | 9 | public class Problem_03_ReverseStackUsingRecursive { 10 | 11 | public static void reverse(Stack stack) { 12 | if (stack.isEmpty()) { 13 | return; 14 | } 15 | int i = getAndRemoveLastElement(stack); 16 | reverse(stack); 17 | stack.push(i); 18 | } 19 | 20 | public static int getAndRemoveLastElement(Stack stack) { 21 | int result = stack.pop(); 22 | if (stack.isEmpty()) { 23 | return result; 24 | } else { 25 | int last = getAndRemoveLastElement(stack); 26 | stack.push(result); 27 | return last; 28 | } 29 | } 30 | 31 | public static void main(String[] args) { 32 | Stack test = new Stack(); 33 | test.push(1); 34 | test.push(2); 35 | test.push(3); 36 | test.push(4); 37 | test.push(5); 38 | reverse(test); 39 | while (!test.isEmpty()) { 40 | System.out.println(test.pop()); 41 | } 42 | 43 | } 44 | 45 | } 46 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter01_Stack&Queue/Q1004.md: -------------------------------------------------------------------------------- 1 | ## 用一个栈实现另一个栈的排序 2 | 3 | **题目:** 4 | >一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。除此之外,可以申请新的变量,但是不能申请额外的数据结构。如何完成排序。 5 | 6 | 7 | ```java 8 | import java.util.Stack; 9 | 10 | public class Problem_05_StackSortStack { 11 | 12 | public static void sortStackByStack(Stack stack) { 13 | Stack help = new Stack(); 14 | while (!stack.isEmpty()) { 15 | int cur = stack.pop(); 16 | while (!help.isEmpty() && help.peek() < cur) { 17 | stack.push(help.pop()); 18 | } 19 | help.push(cur); 20 | } 21 | while (!help.isEmpty()) { 22 | stack.push(help.pop()); 23 | } 24 | } 25 | 26 | public static void main(String[] args) { 27 | Stack stack = new Stack(); 28 | stack.push(3); 29 | stack.push(1); 30 | stack.push(6); 31 | stack.push(2); 32 | stack.push(5); 33 | stack.push(4); 34 | sortStackByStack(stack); 35 | System.out.println(stack.pop()); 36 | System.out.println(stack.pop()); 37 | System.out.println(stack.pop()); 38 | System.out.println(stack.pop()); 39 | System.out.println(stack.pop()); 40 | System.out.println(stack.pop()); 41 | 42 | } 43 | 44 | } 45 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter01_Stack&Queue/Q1006.md: -------------------------------------------------------------------------------- 1 | ## 生成窗口最大值数组 2 | 3 | **题目:** 4 | >有一个整数数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑到一个位置。 5 | 例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时: 6 | ``` 7 | [4 3 5] 4 3 3 6 7 窗口中最大值为5 8 | 4 [3 5 4] 3 3 6 7 窗口中最大值为5 9 | 4 3 [5 4 3] 3 6 7 窗口中最大值为5 10 | 4 3 5 [4 3 3] 6 7 窗口中最大值为4 11 | 4 3 5 4 [3 3 6] 7 窗口中最大值为6 12 | 4 3 5 4 3 [3 6 7] 窗口中最大值为7 13 | ``` 14 | 如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值。 15 | 请实现一个函数。 16 | - 输入:整数数组arr,窗口大小为w。 17 | - 输出:一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。 18 | 19 | 20 | ```java 21 | import java.util.LinkedList; 22 | 23 | public class Problem_07_SlidingWindowMaxArray { 24 | 25 | public static int[] getMaxWindow(int[] arr, int w) { 26 | if (arr == null || w < 1 || arr.length < w) { 27 | return null; 28 | } 29 | LinkedList qmax = new LinkedList(); 30 | int[] res = new int[arr.length - w + 1]; 31 | int index = 0; 32 | for (int i = 0; i < arr.length; i++) { 33 | while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i]) { 34 | qmax.pollLast(); 35 | } 36 | qmax.addLast(i); 37 | if (qmax.peekFirst() == i - w) { 38 | qmax.pollFirst(); 39 | } 40 | if (i >= w - 1) { 41 | res[index++] = arr[qmax.peekFirst()]; 42 | } 43 | } 44 | return res; 45 | } 46 | 47 | // for test 48 | public static void printArray(int[] arr) { 49 | for (int i = 0; i != arr.length; i++) { 50 | System.out.print(arr[i] + " "); 51 | } 52 | System.out.println(); 53 | } 54 | 55 | public static void main(String[] args) { 56 | int[] arr = { 4, 3, 5, 4, 3, 3, 6, 7 }; 57 | int w = 3; 58 | printArray(getMaxWindow(arr, w)); 59 | 60 | } 61 | 62 | } 63 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter01_Stack&Queue/Q1008.md: -------------------------------------------------------------------------------- 1 | ## 求最大子矩阵的大小 2 | 3 | **题目:** 4 | >给定一个整数矩阵map,其中的值只有0和1两种,求其中全是1的所有矩形区域中,最大的矩形区域为1的数量。 5 | ``` 6 | 例如: 7 | 1 1 1 0 8 | 其中,最大的矩形区域有3个1,所以返回3。 9 | 再如: 10 | 1 0 1 1 11 | 1 1 1 1 12 | 1 1 1 0 13 | 其中,最大的矩形区域有6个1,所以返回6。 14 | ``` 15 | 16 | 17 | 18 | ```java 19 | import java.util.Stack; 20 | 21 | public class Problem_09_MaximalRectangle { 22 | 23 | public static int maxRecSize(int[][] map) { 24 | if (map == null || map.length == 0 || map[0].length == 0) { 25 | return 0; 26 | } 27 | int maxArea = 0; 28 | int[] height = new int[map[0].length]; 29 | for (int i = 0; i < map.length; i++) { 30 | for (int j = 0; j < map[0].length; j++) { 31 | height[j] = map[i][j] == 0 ? 0 : height[j] + 1; 32 | } 33 | maxArea = Math.max(maxRecFromBottom(height), maxArea); 34 | } 35 | return maxArea; 36 | } 37 | 38 | public static int maxRecFromBottom(int[] height) { 39 | if (height == null || height.length == 0) { 40 | return 0; 41 | } 42 | int maxArea = 0; 43 | Stack stack = new Stack(); 44 | for (int i = 0; i < height.length; i++) { 45 | while (!stack.isEmpty() && height[i] <= height[stack.peek()]) { 46 | int j = stack.pop(); 47 | int k = stack.isEmpty() ? -1 : stack.peek(); 48 | int curArea = (i - k - 1) * height[j]; 49 | maxArea = Math.max(maxArea, curArea); 50 | } 51 | stack.push(i); 52 | } 53 | while (!stack.isEmpty()) { 54 | int j = stack.pop(); 55 | int k = stack.isEmpty() ? -1 : stack.peek(); 56 | int curArea = (height.length - k - 1) * height[j]; 57 | maxArea = Math.max(maxArea, curArea); 58 | } 59 | return maxArea; 60 | } 61 | 62 | public static void main(String[] args) { 63 | int[][] map = { { 1, 0, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 0 }, }; 64 | System.out.println(maxRecSize(map)); 65 | } 66 | 67 | } 68 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter01_Stack&Queue/Q1009.md: -------------------------------------------------------------------------------- 1 | ## 最大值减去最小值小于或等于num的子数组数量 2 | 3 | **题目:** 4 | >给定数组arr和整数num,共返回有多少个子数组满足如下情况: 5 | max(arr[i..j])-min(arr[i..j])<=num 6 | max(arr[i..j])表示子数组arr[i..j]中的最大值,min(arr[i..j])表示子数组arr[i..j]中的最小值。 7 | 8 | **要求:** 9 | 如果数组长度为N,请实现时间复杂度为O(N)的解法。 10 | 11 | 12 | ```java 13 | import java.util.LinkedList; 14 | 15 | public class Problem_10_AllLessNumSubArray { 16 | 17 | public static int getNum(int[] arr, int num) { 18 | if (arr == null || arr.length == 0) { 19 | return 0; 20 | } 21 | LinkedList qmin = new LinkedList(); 22 | LinkedList qmax = new LinkedList(); 23 | int i = 0; 24 | int j = 0; 25 | int res = 0; 26 | while (i < arr.length) { 27 | while (j < arr.length) { 28 | while (!qmin.isEmpty() && arr[qmin.peekLast()] >= arr[j]) { 29 | qmin.pollLast(); 30 | } 31 | qmin.addLast(j); 32 | while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[j]) { 33 | qmax.pollLast(); 34 | } 35 | qmax.addLast(j); 36 | if (arr[qmax.getFirst()] - arr[qmin.getFirst()] > num) { 37 | break; 38 | } 39 | j++; 40 | } 41 | if (qmin.peekFirst() == i) { 42 | qmin.pollFirst(); 43 | } 44 | if (qmax.peekFirst() == i) { 45 | qmax.pollFirst(); 46 | } 47 | res += j - i; 48 | i++; 49 | } 50 | return res; 51 | } 52 | 53 | // for test 54 | public static int[] getRandomArray(int len) { 55 | if (len < 0) { 56 | return null; 57 | } 58 | int[] arr = new int[len]; 59 | for (int i = 0; i < len; i++) { 60 | arr[i] = (int) (Math.random() * 10); 61 | } 62 | return arr; 63 | } 64 | 65 | // for test 66 | public static void printArray(int[] arr) { 67 | if (arr != null) { 68 | for (int i = 0; i < arr.length; i++) { 69 | System.out.print(arr[i] + " "); 70 | } 71 | System.out.println(); 72 | } 73 | } 74 | 75 | public static void main(String[] args) { 76 | int[] arr = getRandomArray(30); 77 | int num = 5; 78 | printArray(arr); 79 | System.out.println(getNum(arr, num)); 80 | 81 | } 82 | 83 | } 84 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter02_List/Q1001.md: -------------------------------------------------------------------------------- 1 | ## 打印两个有序链表的公共部分 2 | 3 | **题目:** 4 | >给定两个有序链表的头指针head1和head2,打印两个链表的公共部分。 5 | 6 | ```java 7 | public class Problem_01_PrintCommonPart { 8 | 9 | public static class Node { 10 | public int value; 11 | public Node next; 12 | public Node(int data) { 13 | this.value = data; 14 | } 15 | } 16 | 17 | public static void printCommonPart(Node head1, Node head2) { 18 | System.out.print("Common Part: "); 19 | while (head1 != null && head2 != null) { 20 | if (head1.value < head2.value) { 21 | head1 = head1.next; 22 | } else if (head1.value > head2.value) { 23 | head2 = head2.next; 24 | } else { 25 | System.out.print(head1.value + " "); 26 | head1 = head1.next; 27 | head2 = head2.next; 28 | } 29 | } 30 | System.out.println(); 31 | } 32 | 33 | public static void printLinkedList(Node node) { 34 | System.out.print("Linked List: "); 35 | while (node != null) { 36 | System.out.print(node.value + " "); 37 | node = node.next; 38 | } 39 | System.out.println(); 40 | } 41 | 42 | public static void main(String[] args) { 43 | Node node1 = new Node(2); 44 | node1.next = new Node(3); 45 | node1.next.next = new Node(5); 46 | node1.next.next.next = new Node(6); 47 | 48 | Node node2 = new Node(1); 49 | node2.next = new Node(2); 50 | node2.next.next = new Node(5); 51 | node2.next.next.next = new Node(7); 52 | node2.next.next.next.next = new Node(8); 53 | 54 | printLinkedList(node1); 55 | printLinkedList(node2); 56 | printCommonPart(node1, node2); 57 | 58 | } 59 | 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter02_List/Q1017.md: -------------------------------------------------------------------------------- 1 | ## 一种怪异的节点删除方式 2 | 3 | **题目:** 4 | >链表节点值类型为int型,给定一个链表中的节点node,但不给定整个链表的头节点。如何在链表中删除node?请实现这个函数,并并分析这么会出现哪些问题。 5 | 要求:时间复杂度为O(1)。 6 | 7 | ```java 8 | public class Problem_17_RemoveNodeWired { 9 | 10 | public static class Node { 11 | public int value; 12 | public Node next; 13 | 14 | public Node(int data) { 15 | this.value = data; 16 | } 17 | } 18 | 19 | public static void removeNodeWired(Node node) { 20 | if (node == null) { 21 | return; 22 | } 23 | Node next = node.next; 24 | if (next == null) { 25 | throw new RuntimeException("can not remove last node."); 26 | } 27 | node.value = next.value; 28 | node.next = next.next; 29 | } 30 | 31 | public static void printLinkedList(Node head) { 32 | System.out.print("Linked List: "); 33 | while (head != null) { 34 | System.out.print(head.value + " "); 35 | head = head.next; 36 | } 37 | System.out.println(); 38 | } 39 | 40 | public static void main(String[] args) { 41 | Node head = new Node(1); 42 | head.next = new Node(2); 43 | head.next.next = new Node(3); 44 | Node node = head; 45 | printLinkedList(head); 46 | removeNodeWired(node); 47 | printLinkedList(head); 48 | 49 | head = new Node(1); 50 | head.next = new Node(2); 51 | head.next.next = new Node(3); 52 | node = head.next; 53 | printLinkedList(head); 54 | removeNodeWired(node); 55 | printLinkedList(head); 56 | 57 | // head = new Node(1); 58 | // head.next = new Node(2); 59 | // head.next.next = new Node(3); 60 | // node = head.next.next; 61 | // printLinkedList(head); 62 | // removeNodeWired(node); 63 | // printLinkedList(head); 64 | 65 | } 66 | 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter02_List/Q1018.md: -------------------------------------------------------------------------------- 1 | ## 向有序的环形单链表中插入新节点 2 | 3 | **题目:** 4 | >一个环形单链表从头节点head开始不降序,同时由最后的节点指回头节点。给定这样一个环形单链表的头节点head和个整数num,请生成节点值为num的新节点,并插入到这个环形链表中,保证调整后的链表依然有序。 5 | 6 | 7 | ```java 8 | public class Problem_18_InsertNumToCircularList { 9 | 10 | public static class Node { 11 | public int value; 12 | public Node next; 13 | 14 | public Node(int data) { 15 | this.value = data; 16 | } 17 | } 18 | 19 | public static Node insertNum(Node head, int num) { 20 | Node node = new Node(num); 21 | if (head == null) { 22 | node.next = node; 23 | return node; 24 | } 25 | Node pre = head; 26 | Node cur = head.next; 27 | while (cur != head) { 28 | if (pre.value <= num && cur.value >= num) { 29 | break; 30 | } 31 | pre = cur; 32 | cur = cur.next; 33 | } 34 | pre.next = node; 35 | node.next = cur; 36 | return head.value < num ? head : node; 37 | } 38 | 39 | public static void printCircularList(Node head) { 40 | if (head == null) { 41 | return; 42 | } 43 | System.out.print("Circular List: " + head.value + " "); 44 | Node cur = head.next; 45 | while (cur != head) { 46 | System.out.print(cur.value + " "); 47 | cur = cur.next; 48 | } 49 | System.out.println("-> " + head.value); 50 | } 51 | 52 | public static void main(String[] args) { 53 | Node head = null; 54 | head = insertNum(head, 2); 55 | printCircularList(head); 56 | head = insertNum(head, 1); 57 | printCircularList(head); 58 | head = insertNum(head, 4); 59 | printCircularList(head); 60 | head = insertNum(head, 3); 61 | printCircularList(head); 62 | head = insertNum(head, 5); 63 | printCircularList(head); 64 | head = insertNum(head, 0); 65 | printCircularList(head); 66 | 67 | } 68 | 69 | } 70 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter03_BT/Q1003.md: -------------------------------------------------------------------------------- 1 | ## 如何较为直观地打印二叉树 2 | 3 | **题目:** 4 | >二叉树可以用常规的三种遍历结果来描述其结构,但是不够直观,尤其是二叉树中有重复值的时候,仅通过三种遍历的结果来构造二叉树的真实结构更是难上加难,有时则根本不可能。给定一棵二叉树的头节点head,己知二叉树节点值的类型为32位整型,请实现一个打印二叉树的函数,可以直观地展示树的形状,也便于画出真实的结构。 5 | 6 | ```java 7 | public class Problem_03_PrintBinaryTree { 8 | 9 | public static class Node { 10 | public int value; 11 | public Node left; 12 | public Node right; 13 | 14 | public Node(int data) { 15 | this.value = data; 16 | } 17 | } 18 | 19 | public static void printTree(Node head) { 20 | System.out.println("Binary Tree:"); 21 | printInOrder(head, 0, "H", 17); 22 | System.out.println(); 23 | } 24 | 25 | public static void printInOrder(Node head, int height, String to, int len) { 26 | if (head == null) { 27 | return; 28 | } 29 | printInOrder(head.right, height + 1, "v", len); 30 | String val = to + head.value + to; 31 | int lenM = val.length(); 32 | int lenL = (len - lenM) / 2; 33 | int lenR = len - lenM - lenL; 34 | val = getSpace(lenL) + val + getSpace(lenR); 35 | System.out.println(getSpace(height * len) + val); 36 | printInOrder(head.left, height + 1, "^", len); 37 | } 38 | 39 | public static String getSpace(int num) { 40 | String space = " "; 41 | StringBuffer buf = new StringBuffer(""); 42 | for (int i = 0; i < num; i++) { 43 | buf.append(space); 44 | } 45 | return buf.toString(); 46 | } 47 | 48 | public static void main(String[] args) { 49 | Node head = new Node(1); 50 | head.left = new Node(-222222222); 51 | head.right = new Node(3); 52 | head.left.left = new Node(Integer.MIN_VALUE); 53 | head.right.left = new Node(55555555); 54 | head.right.right = new Node(66); 55 | head.left.left.right = new Node(777); 56 | printTree(head); 57 | 58 | head = new Node(1); 59 | head.left = new Node(2); 60 | head.right = new Node(3); 61 | head.left.left = new Node(4); 62 | head.right.left = new Node(5); 63 | head.right.right = new Node(6); 64 | head.left.left.right = new Node(7); 65 | printTree(head); 66 | 67 | head = new Node(1); 68 | head.left = new Node(1); 69 | head.right = new Node(1); 70 | head.left.left = new Node(1); 71 | head.right.left = new Node(1); 72 | head.right.right = new Node(1); 73 | head.left.left.right = new Node(1); 74 | printTree(head); 75 | 76 | } 77 | 78 | } 79 | 80 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter03_BT/Q1011.md: -------------------------------------------------------------------------------- 1 | ## 判断t1树是否包含t2树全部的拓扑结构 2 | 3 | **题目:** 4 | >给定彼此独立的两棵树头节点分别为t1和t2,判断t1树是否包含t2树全部的拓扑结构。 5 | 6 | 7 | ```java 8 | 9 | public class Problem_11_T1ContainsT2Topology { 10 | 11 | public static class Node { 12 | public int value; 13 | public Node left; 14 | public Node right; 15 | 16 | public Node(int data) { 17 | this.value = data; 18 | } 19 | } 20 | 21 | public static boolean contains(Node t1, Node t2) { 22 | if (t2 == null) { 23 | return true; 24 | } 25 | if (t1 == null) { 26 | return false; 27 | } 28 | return check(t1, t2) || contains(t1.left, t2) || contains(t1.right, t2); 29 | } 30 | 31 | public static boolean check(Node h, Node t2) { 32 | if (t2 == null) { 33 | return true; 34 | } 35 | if (h == null || h.value != t2.value) { 36 | return false; 37 | } 38 | return check(h.left, t2.left) && check(h.right, t2.right); 39 | } 40 | 41 | public static void main(String[] args) { 42 | Node t1 = new Node(1); 43 | t1.left = new Node(2); 44 | t1.right = new Node(3); 45 | t1.left.left = new Node(4); 46 | t1.left.right = new Node(5); 47 | t1.right.left = new Node(6); 48 | t1.right.right = new Node(7); 49 | t1.left.left.left = new Node(8); 50 | t1.left.left.right = new Node(9); 51 | t1.left.right.left = new Node(10); 52 | 53 | Node t2 = new Node(2); 54 | t2.left = new Node(4); 55 | t2.left.left = new Node(8); 56 | t2.right = new Node(5); 57 | 58 | System.out.println(contains(t1, t2)); 59 | 60 | } 61 | 62 | } 63 | 64 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter03_BT/Q1013.md: -------------------------------------------------------------------------------- 1 | ## 判断二叉树是否为平衡二叉树 2 | 3 | **题目:** 4 | >平衡二叉树的性质为:要么是一棵空树,要么任何一个节点的左右子树高度差的绝对值不超过1。给定一棵二叉树的头节点head,判断这棵二叉树是否为平衡二叉树。 5 | 6 | **要求:** 7 | >如果二叉树的节点数为N, 要求时间复杂度为 O(N)。 8 | 9 | ```java 10 | public class Problem_13_IsBalancedTree { 11 | 12 | public static class Node { 13 | public int value; 14 | public Node left; 15 | public Node right; 16 | 17 | public Node(int data) { 18 | this.value = data; 19 | } 20 | } 21 | 22 | public static boolean isBalance(Node head) { 23 | boolean[] res = new boolean[1]; 24 | res[0] = true; 25 | getHeight(head, 1, res); 26 | return res[0]; 27 | } 28 | 29 | public static int getHeight(Node head, int level, boolean[] res) { 30 | if (head == null) { 31 | return level; 32 | } 33 | int lH = getHeight(head.left, level + 1, res); 34 | if (!res[0]) { 35 | return level; 36 | } 37 | int rH = getHeight(head.right, level + 1, res); 38 | if (!res[0]) { 39 | return level; 40 | } 41 | if (Math.abs(lH - rH) > 1) { 42 | res[0] = false; 43 | } 44 | return Math.max(lH, rH); 45 | } 46 | 47 | public static void main(String[] args) { 48 | Node head = new Node(1); 49 | head.left = new Node(2); 50 | head.right = new Node(3); 51 | head.left.left = new Node(4); 52 | head.left.right = new Node(5); 53 | head.right.left = new Node(6); 54 | head.right.right = new Node(7); 55 | 56 | System.out.println(isBalance(head)); 57 | 58 | } 59 | 60 | } 61 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter03_BT/Q1016.md: -------------------------------------------------------------------------------- 1 | ## 通过有序数组生成平衡搜索二叉树 2 | 3 | **题目:** 4 | >给定一个有序数组sortArr,已知其中没有重复值,用这个有序数组生成一棵平衡搜索二叉树,并且该搜索二叉树中序遍历的结果与sortArr一致。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_16_SortedArrayToBalancedBST { 10 | 11 | public static class Node { 12 | public int value; 13 | public Node left; 14 | public Node right; 15 | 16 | public Node(int data) { 17 | this.value = data; 18 | } 19 | } 20 | 21 | public static Node generateTree(int[] sortArr) { 22 | if (sortArr == null) { 23 | return null; 24 | } 25 | return generate(sortArr, 0, sortArr.length - 1); 26 | } 27 | 28 | public static Node generate(int[] sortArr, int start, int end) { 29 | if (start > end) { 30 | return null; 31 | } 32 | int mid = (start + end) / 2; 33 | Node head = new Node(sortArr[mid]); 34 | head.left = generate(sortArr, start, mid - 1); 35 | head.right = generate(sortArr, mid + 1, end); 36 | return head; 37 | } 38 | 39 | // for test -- print tree 40 | public static void printTree(Node head) { 41 | System.out.println("Binary Tree:"); 42 | printInOrder(head, 0, "H", 17); 43 | System.out.println(); 44 | } 45 | 46 | public static void printInOrder(Node head, int height, String to, int len) { 47 | if (head == null) { 48 | return; 49 | } 50 | printInOrder(head.right, height + 1, "v", len); 51 | String val = to + head.value + to; 52 | int lenM = val.length(); 53 | int lenL = (len - lenM) / 2; 54 | int lenR = len - lenM - lenL; 55 | val = getSpace(lenL) + val + getSpace(lenR); 56 | System.out.println(getSpace(height * len) + val); 57 | printInOrder(head.left, height + 1, "^", len); 58 | } 59 | 60 | public static String getSpace(int num) { 61 | String space = " "; 62 | StringBuffer buf = new StringBuffer(""); 63 | for (int i = 0; i < num; i++) { 64 | buf.append(space); 65 | } 66 | return buf.toString(); 67 | } 68 | 69 | public static void main(String[] args) { 70 | int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 71 | printTree(generateTree(arr)); 72 | 73 | } 74 | 75 | } 76 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter03_BT/Q1020.md: -------------------------------------------------------------------------------- 1 | ## 二叉树节点问的最大距离问题 2 | 3 | **题目:** 4 | >从二叉树的节点A出发,可以向上或者向下走,但沿途的节点只能经过一次,当到达节点B时,路径上的节点数叫作A到B的距离。 5 | 6 | 7 | ```java 8 | public class Problem_20_MaxDistanceInTree { 9 | 10 | public static class Node { 11 | public int value; 12 | public Node left; 13 | public Node right; 14 | 15 | public Node(int data) { 16 | this.value = data; 17 | } 18 | } 19 | 20 | public static int maxDistance(Node head) { 21 | int[] record = new int[1]; 22 | return posOrder(head, record); 23 | } 24 | 25 | public static int posOrder(Node head, int[] record) { 26 | if (head == null) { 27 | record[0] = 0; 28 | return 0; 29 | } 30 | int lMax = posOrder(head.left, record); 31 | int maxfromLeft = record[0]; 32 | int rMax = posOrder(head.right, record); 33 | int maxFromRight = record[0]; 34 | int curNodeMax = maxfromLeft + maxFromRight + 1; 35 | record[0] = Math.max(maxfromLeft, maxFromRight) + 1; 36 | return Math.max(Math.max(lMax, rMax), curNodeMax); 37 | } 38 | 39 | public static void main(String[] args) { 40 | Node head1 = new Node(1); 41 | head1.left = new Node(2); 42 | head1.right = new Node(3); 43 | head1.left.left = new Node(4); 44 | head1.left.right = new Node(5); 45 | head1.right.left = new Node(6); 46 | head1.right.right = new Node(7); 47 | head1.left.left.left = new Node(8); 48 | head1.right.left.right = new Node(9); 49 | System.out.println(maxDistance(head1)); 50 | 51 | Node head2 = new Node(1); 52 | head2.left = new Node(2); 53 | head2.right = new Node(3); 54 | head2.right.left = new Node(4); 55 | head2.right.right = new Node(5); 56 | head2.right.left.left = new Node(6); 57 | head2.right.right.right = new Node(7); 58 | head2.right.left.left.left = new Node(8); 59 | head2.right.right.right.right = new Node(9); 60 | System.out.println(maxDistance(head2)); 61 | 62 | } 63 | 64 | } 65 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter03_BT/Q1022.md: -------------------------------------------------------------------------------- 1 | ## 通过先序和中序数组生成后序数组 2 | 3 | **题目:** 4 | >己知一棵二叉树所有的节点值都不同,给定这棵树正确的先序和中序数组,不要重建整棵树,而是通过这两个数组直接生成正确的后序数组。 5 | 6 | 7 | ```java 8 | import java.util.HashMap; 9 | 10 | public class Problem_22_PreAndInArrayToPosArray { 11 | 12 | public static int[] getPosArray(int[] pre, int[] in) { 13 | if (pre == null || in == null) { 14 | return null; 15 | } 16 | int len = pre.length; 17 | int[] pos = new int[len]; 18 | HashMap map = new HashMap(); 19 | for (int i = 0; i < len; i++) { 20 | map.put(in[i], i); 21 | } 22 | setPos(pre, 0, len - 1, in, 0, len - 1, pos, len - 1, map); 23 | return pos; 24 | } 25 | 26 | // 从右往左依次填好后序数组s 27 | // si为后序数组s该填的位置 28 | // 返回值为s该填的下一个位置 29 | public static int setPos(int[] p, int pi, int pj, int[] n, int ni, int nj, 30 | int[] s, int si, HashMap map) { 31 | if (pi > pj) { 32 | return si; 33 | } 34 | s[si--] = p[pi]; 35 | int i = map.get(p[pi]); 36 | si = setPos(p, pj - nj + i + 1, pj, n, i + 1, nj, s, si, map); 37 | return setPos(p, pi + 1, pi + i - ni, n, ni, i - 1, s, si, map); 38 | } 39 | 40 | public static void printArray(int[] arr) { 41 | if (arr == null) { 42 | return; 43 | } 44 | for (int i = 0; i != arr.length; i++) { 45 | System.out.print(arr[i] + " "); 46 | } 47 | System.out.println(); 48 | } 49 | 50 | public static void main(String[] args) { 51 | int[] pre = { 1, 2, 4, 5, 3, 6, 7 }; 52 | int[] in = { 4, 2, 5, 1, 6, 3, 7 }; 53 | int[] pos = getPosArray(pre, in); 54 | printArray(pos); 55 | 56 | } 57 | } 58 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter03_BT/Q1024.md: -------------------------------------------------------------------------------- 1 | ## 统计完全二叉树的节点数 2 | 3 | **题目:** 4 | >给定一棵完全二叉树的头节点head,返回这棵树的节点个数。 5 | 6 | 7 | ```java 8 | public class Problem_24_CompleteTreeNodeNumber { 9 | 10 | public static class Node { 11 | public int value; 12 | public Node left; 13 | public Node right; 14 | 15 | public Node(int data) { 16 | this.value = data; 17 | } 18 | } 19 | 20 | public static int nodeNum(Node head) { 21 | if (head == null) { 22 | return 0; 23 | } 24 | return bs(head, 1, mostLeftLevel(head, 1)); 25 | } 26 | 27 | public static int bs(Node node, int l, int h) { 28 | if (l == h) { 29 | return 1; 30 | } 31 | if (mostLeftLevel(node.right, l + 1) == h) { 32 | return (1 << (h - l)) + bs(node.right, l + 1, h); 33 | } else { 34 | return (1 << (h - l - 1)) + bs(node.left, l + 1, h); 35 | } 36 | } 37 | 38 | public static int mostLeftLevel(Node node, int level) { 39 | while (node != null) { 40 | level++; 41 | node = node.left; 42 | } 43 | return level - 1; 44 | } 45 | 46 | public static void main(String[] args) { 47 | Node head = new Node(1); 48 | head.left = new Node(2); 49 | head.right = new Node(3); 50 | head.left.left = new Node(4); 51 | head.left.right = new Node(5); 52 | head.right.left = new Node(6); 53 | System.out.println(nodeNum(head)); 54 | 55 | } 56 | 57 | } 58 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter04_RecursionAndDP/Q1006.md: -------------------------------------------------------------------------------- 1 | ## 汉诺塔问题 2 | 3 | **题目:** 4 | >给定一个整数n,代表汉诺塔游戏中从小到大放置的n个圆盘,假设开始时所有的圆盘都放在左边的柱子上,想按照汉诺塔游戏的要求把所有的圆盘都移到右边的柱子上。实现函数打印最优移动轨迹。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_06_HanoiProblem { 10 | 11 | public static void hanoi(int n) { 12 | if (n > 0) { 13 | func(n, "left", "mid", "right"); 14 | } 15 | } 16 | 17 | public static void func(int n, String from, String mid, String to) { 18 | if (n == 1) { 19 | System.out.println("move from " + from + " to " + to); 20 | } else { 21 | func(n - 1, from, to, mid); 22 | func(1, from, mid, to); 23 | func(n - 1, mid, from, to); 24 | } 25 | } 26 | 27 | public static int step1(int[] arr) { 28 | if (arr == null || arr.length == 0) { 29 | return -1; 30 | } 31 | return process(arr, arr.length - 1, 1, 2, 3); 32 | } 33 | 34 | public static int process(int[] arr, int i, int from, int mid, int to) { 35 | if (i == -1) { 36 | return 0; 37 | } 38 | if (arr[i] != from && arr[i] != to) { 39 | return -1; 40 | } 41 | if (arr[i] == from) { 42 | return process(arr, i - 1, from, to, mid); 43 | } else { 44 | int rest = process(arr, i - 1, mid, from, to); 45 | if (rest == -1) { 46 | return -1; 47 | } 48 | return (1 << i) + rest; 49 | } 50 | } 51 | 52 | public static int step2(int[] arr) { 53 | if (arr == null || arr.length == 0) { 54 | return -1; 55 | } 56 | int from = 1; 57 | int mid = 2; 58 | int to = 3; 59 | int i = arr.length - 1; 60 | int res = 0; 61 | int tmp = 0; 62 | while (i >= 0) { 63 | if (arr[i] != from && arr[i] != to) { 64 | return -1; 65 | } 66 | if (arr[i] == to) { 67 | res += 1 << i; 68 | tmp = from; 69 | from = mid; 70 | } else { 71 | tmp = to; 72 | to = mid; 73 | } 74 | mid = tmp; 75 | i--; 76 | } 77 | return res; 78 | } 79 | 80 | public static void main(String[] args) { 81 | int n = 4; 82 | hanoi(n); 83 | 84 | int[] arr = { 3, 3, 2, 1 }; 85 | System.out.println(step1(arr)); 86 | System.out.println(step2(arr)); 87 | 88 | } 89 | } 90 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter04_RecursionAndDP/Q1007.md: -------------------------------------------------------------------------------- 1 | ## 最长公共子序列问题 2 | 3 | **题目:** 4 | >给定两个字符串strl和str2,返回两个字符串的最长公共子序列。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_07_LCSubsequence { 10 | 11 | public static String lcse(String str1, String str2) { 12 | if (str1 == null || str2 == null || str1.equals("") || str2.equals("")) { 13 | return ""; 14 | } 15 | char[] chs1 = str1.toCharArray(); 16 | char[] chs2 = str2.toCharArray(); 17 | int[][] dp = getdp(chs1, chs2); 18 | int m = chs1.length - 1; 19 | int n = chs2.length - 1; 20 | char[] res = new char[dp[m][n]]; 21 | int index = res.length - 1; 22 | while (index >= 0) { 23 | if (n > 0 && dp[m][n] == dp[m][n - 1]) { 24 | n--; 25 | } else if (m > 0 && dp[m][n] == dp[m - 1][n]) { 26 | m--; 27 | } else { 28 | res[index--] = chs1[m]; 29 | m--; 30 | n--; 31 | } 32 | } 33 | return String.valueOf(res); 34 | } 35 | 36 | public static int[][] getdp(char[] str1, char[] str2) { 37 | int[][] dp = new int[str1.length][str2.length]; 38 | dp[0][0] = str1[0] == str2[0] ? 1 : 0; 39 | for (int i = 1; i < str1.length; i++) { 40 | dp[i][0] = Math.max(dp[i - 1][0], str1[i] == str2[0] ? 1 : 0); 41 | } 42 | for (int j = 1; j < str2.length; j++) { 43 | dp[0][j] = Math.max(dp[0][j - 1], str1[0] == str2[j] ? 1 : 0); 44 | } 45 | for (int i = 1; i < str1.length; i++) { 46 | for (int j = 1; j < str2.length; j++) { 47 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 48 | if (str1[i] == str2[j]) { 49 | dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1); 50 | } 51 | } 52 | } 53 | return dp; 54 | } 55 | 56 | public static void main(String[] args) { 57 | String str1 = "A1BC2D3EFGH45I6JK7LMN"; 58 | String str2 = "12OPQ3RST4U5V6W7XYZ"; 59 | System.out.println(lcse(str1, str2)); 60 | 61 | } 62 | } 63 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter04_RecursionAndDP/Q1012.md: -------------------------------------------------------------------------------- 1 | ## 数字字符串转换为字母组合的种数 2 | 3 | **题目:** 4 | >给定一个字符串str,str全部由数字宇符组成,如果str中某一个或某相邻两个字符组成的子串值在l~26之间,则这个子串可以转换为一个字母。规定”1”转换为”A”,”2”转换为“B”,..."26"转换为“Z”。写一个函数,求str有多少种不同的转换结果,并返回种数。 5 | 6 | ```java 7 | public class Problem_12_NumberToLetter { 8 | 9 | public static int num1(String str) { 10 | if (str == null || str.equals("")) { 11 | return 0; 12 | } 13 | char[] chs = str.toCharArray(); 14 | return process(chs, 0); 15 | } 16 | 17 | public static int process(char[] chs, int i) { 18 | if (i == chs.length) { 19 | return 1; 20 | } 21 | if (chs[i] == '0') { 22 | return 0; 23 | } 24 | int res = process(chs, i + 1); 25 | if (i + 1 < chs.length && (chs[i] - '0') * 10 + chs[i + 1] - '0' < 27) { 26 | res += process(chs, i + 2); 27 | } 28 | return res; 29 | } 30 | 31 | public static int num2(String str) { 32 | if (str == null || str.equals("")) { 33 | return 0; 34 | } 35 | char[] chs = str.toCharArray(); 36 | int cur = chs[chs.length - 1] == '0' ? 0 : 1; 37 | int next = 1; 38 | int tmp = 0; 39 | for (int i = chs.length - 2; i >= 0; i--) { 40 | if (chs[i] == '0') { 41 | next = cur; 42 | cur = 0; 43 | } else { 44 | tmp = cur; 45 | if ((chs[i] - '0') * 10 + chs[i + 1] - '0' < 27) { 46 | cur += next; 47 | } 48 | next = tmp; 49 | } 50 | } 51 | return cur; 52 | } 53 | 54 | public static void main(String[] args) { 55 | String str = "781231783161018231"; 56 | System.out.println(num1(str)); 57 | System.out.println(num2(str)); 58 | 59 | } 60 | } 61 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter04_RecursionAndDP/Q1014.md: -------------------------------------------------------------------------------- 1 | ## 排成一条线的纸牌博弈问题 2 | 3 | **题目:** 4 | >给定一个整型数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿,但是每个玩家每次只能拿走最左或最右的纸牌,玩家A和玩家B都绝顶聪明。请返回最后获胜者的分数。 5 | 6 | 7 | ```java 8 | public class Problem_14_CardsInLine { 9 | 10 | public static int win1(int[] arr) { 11 | if (arr == null || arr.length == 0) { 12 | return 0; 13 | } 14 | return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1)); 15 | } 16 | 17 | public static int f(int[] arr, int i, int j) { 18 | if (i == j) { 19 | return arr[i]; 20 | } 21 | return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1)); 22 | } 23 | 24 | public static int s(int[] arr, int i, int j) { 25 | if (i == j) { 26 | return 0; 27 | } 28 | return Math.min(f(arr, i + 1, j), f(arr, i, j - 1)); 29 | } 30 | 31 | public static int win2(int[] arr) { 32 | if (arr == null || arr.length == 0) { 33 | return 0; 34 | } 35 | int[][] f = new int[arr.length][arr.length]; 36 | int[][] s = new int[arr.length][arr.length]; 37 | for (int j = 0; j < arr.length; j++) { 38 | f[j][j] = arr[j]; 39 | for (int i = j - 1; i >= 0; i--) { 40 | f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]); 41 | s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]); 42 | } 43 | } 44 | return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]); 45 | } 46 | 47 | public static void main(String[] args) { 48 | int[] arr = { 1, 9, 1 }; 49 | System.out.println(win1(arr)); 50 | System.out.println(win2(arr)); 51 | 52 | } 53 | 54 | } 55 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter04_RecursionAndDP/Q1015.md: -------------------------------------------------------------------------------- 1 | ## 跳跃游戏 2 | 3 | **题目:** 4 | >给定数组arr, arr[i]=k代表可以从位置i向右跳l~k个距离。比如,arr[2]==3,代表从位置2可以跳到位置3、位置4或位置5。如果从位置0出发,返回最少跳几次能跳到 arr最后的位置上。 5 | 6 | ```java 7 | public class Problem_15_JumpGame { 8 | 9 | public static int jump(int[] arr) { 10 | if (arr == null || arr.length == 0) { 11 | return 0; 12 | } 13 | int jump = 0; 14 | int cur = 0; 15 | int next = 0; 16 | for (int i = 0; i < arr.length; i++) { 17 | if (cur < i) { 18 | jump++; 19 | cur = next; 20 | } 21 | next = Math.max(next, i + arr[i]); 22 | } 23 | return jump; 24 | } 25 | 26 | public static void main(String[] args) { 27 | int[] arr = { 3, 2, 3, 1, 1, 4 }; 28 | System.out.println(jump(arr)); 29 | 30 | } 31 | 32 | } 33 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter04_RecursionAndDP/Q1016.md: -------------------------------------------------------------------------------- 1 | ## 数组中的最长连续序列 2 | 3 | **题目:** 4 | >给定无序数组arr, 返回其中最长的连续序列的长度。 5 | 6 | 7 | 8 | ```java 9 | import java.util.HashMap; 10 | 11 | public class Problem_16_LongestConsecutive { 12 | 13 | public static int longestConsecutive(int[] arr) { 14 | if (arr == null || arr.length == 0) { 15 | return 0; 16 | } 17 | int max = 1; 18 | HashMap map = new HashMap(); 19 | for (int i = 0; i < arr.length; i++) { 20 | if (!map.containsKey(arr[i])) { 21 | map.put(arr[i], 1); 22 | if (map.containsKey(arr[i] - 1)) { 23 | max = Math.max(max, merge(map, arr[i] - 1, arr[i])); 24 | } 25 | if (map.containsKey(arr[i] + 1)) { 26 | max = Math.max(max, merge(map, arr[i], arr[i] + 1)); 27 | } 28 | } 29 | } 30 | return max; 31 | } 32 | 33 | public static int merge(HashMap map, int less, int more) { 34 | int left = less - map.get(less) + 1; 35 | int right = more + map.get(more) - 1; 36 | int len = right - left + 1; 37 | map.put(left, len); 38 | map.put(right, len); 39 | return len; 40 | } 41 | 42 | public static void main(String[] args) { 43 | int[] arr = { 100, 4, 200, 1, 3, 2 }; 44 | System.out.println(longestConsecutive(arr)); 45 | 46 | } 47 | 48 | } 49 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter04_RecursionAndDP/Q1017.md: -------------------------------------------------------------------------------- 1 | ## N皇后问题 2 | 3 | **题目:** 4 | >N皇后问题是指在 NxN 的棋盘上要摆N个皇后, 要求任何两个皇后不同行、不同列,也不在同一条斜线上。给定一个整数n,返回n皇后的摆法有多少种。 5 | 6 | ```java 7 | public class Problem_17_NQueens { 8 | 9 | public static int num1(int n) { 10 | if (n < 1) { 11 | return 0; 12 | } 13 | int[] record = new int[n]; 14 | return process1(0, record, n); 15 | } 16 | 17 | public static int process1(int i, int[] record, int n) { 18 | if (i == n) { 19 | return 1; 20 | } 21 | int res = 0; 22 | for (int j = 0; j < n; j++) { 23 | if (isValid(record, i, j)) { 24 | record[i] = j; 25 | res += process1(i + 1, record, n); 26 | } 27 | } 28 | return res; 29 | } 30 | 31 | public static boolean isValid(int[] record, int i, int j) { 32 | for (int k = 0; k < i; k++) { 33 | if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) { 34 | return false; 35 | } 36 | } 37 | return true; 38 | } 39 | 40 | public static int num2(int n) { 41 | // 因为本方法中位运算的载体是int型变量,所以该方法只能算1~32皇后问题 42 | // 如果想计算更多的皇后问题,需使用包含更多位的变量 43 | if (n < 1 || n > 32) { 44 | return 0; 45 | } 46 | int upperLim = n == 32 ? -1 : (1 << n) - 1; 47 | return process2(upperLim, 0, 0, 0); 48 | } 49 | 50 | public static int process2(int upperLim, int colLim, int leftDiaLim, 51 | int rightDiaLim) { 52 | if (colLim == upperLim) { 53 | return 1; 54 | } 55 | int pos = 0; 56 | int mostRightOne = 0; 57 | pos = upperLim & (~(colLim | leftDiaLim | rightDiaLim)); 58 | int res = 0; 59 | while (pos != 0) { 60 | mostRightOne = pos & (~pos + 1); 61 | pos = pos - mostRightOne; 62 | res += process2(upperLim, colLim | mostRightOne, 63 | (leftDiaLim | mostRightOne) << 1, 64 | (rightDiaLim | mostRightOne) >>> 1); 65 | } 66 | return res; 67 | } 68 | 69 | public static void main(String[] args) { 70 | int n = 8; 71 | 72 | long start = System.currentTimeMillis(); 73 | System.out.println(num2(n)); 74 | long end = System.currentTimeMillis(); 75 | System.out.println("cost time: " + (end - start) + "ms"); 76 | 77 | start = System.currentTimeMillis(); 78 | System.out.println(num1(n)); 79 | end = System.currentTimeMillis(); 80 | System.out.println("cost time: " + (end - start) + "ms"); 81 | 82 | } 83 | } 84 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1001.md: -------------------------------------------------------------------------------- 1 | ## 判断两个字符串是否互为变形词 2 | 3 | **题目:** 4 | >给定两个字符串str1和str2,如果strl和str2中出现的字符种类一样且每种字符出现的次数也一样,那么str1与str2互为变形词。请实现函数判断两个字符串是否互为变形词。 5 | 6 | ```java 7 | public class Problem_01_IsDeformation { 8 | 9 | public static boolean isDeformation(String str1, String str2) { 10 | if (str1 == null || str2 == null || str1.length() != str2.length()) { 11 | return false; 12 | } 13 | char[] chas1 = str1.toCharArray(); 14 | char[] chas2 = str2.toCharArray(); 15 | int[] map = new int[256]; 16 | for (int i = 0; i < chas1.length; i++) { 17 | map[chas1[i]]++; 18 | } 19 | for (int i = 0; i < chas2.length; i++) { 20 | if (map[chas2[i]]-- == 0) { 21 | return false; 22 | } 23 | } 24 | return true; 25 | } 26 | 27 | public static void main(String[] args) { 28 | String A = "abcabcabc"; 29 | String B = "bcacbaacb"; 30 | System.out.println(isDeformation(A, B)); 31 | 32 | } 33 | 34 | } 35 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1002.md: -------------------------------------------------------------------------------- 1 | ## 字符串中数字子串的求和 2 | 3 | **题目:** 4 | >给定一个字符串str,求其中全部数字串所代表的数字之和。 5 | 6 | 7 | ```java 8 | public class Problem_02_AllNumbersSum { 9 | 10 | public static int numSum(String str) { 11 | if (str == null) { 12 | return 0; 13 | } 14 | char[] charArr = str.toCharArray(); 15 | int res = 0; 16 | int num = 0; 17 | boolean posi = true; 18 | int cur = 0; 19 | for (int i = 0; i < charArr.length; i++) { 20 | cur = charArr[i] - '0'; 21 | if (cur < 0 || cur > 9) { 22 | res += num; 23 | num = 0; 24 | if (charArr[i] == '-') { 25 | if (i - 1 > -1 && charArr[i - 1] == '-') { 26 | posi = !posi; 27 | } else { 28 | posi = false; 29 | } 30 | } else { 31 | posi = true; 32 | } 33 | } else { 34 | num = num * 10 + (posi ? cur : -cur); 35 | } 36 | } 37 | res += num; 38 | return res; 39 | } 40 | 41 | public static void main(String[] args) { 42 | String test = "1K-100ABC500D-T--100F200G!!100H---300"; 43 | System.out.println(numSum(test)); 44 | 45 | } 46 | 47 | } 48 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1003.md: -------------------------------------------------------------------------------- 1 | ## 去掉字符串中连续出现k个0的子串/b处的节点 2 | 3 | **题目:** 4 | >给定一个字符串str和一个整数k,如果str中正好有连续的k个’0’字符出现时,把k个连续的’0’字符去除, 返回处理后的字符串。 5 | 6 | ```java 7 | public class Problem_03_RemoveKZeros { 8 | 9 | public static String removeKZeros(String str, int k) { 10 | if (str == null || k < 1) { 11 | return str; 12 | } 13 | char[] chas = str.toCharArray(); 14 | int count = 0, start = -1; 15 | for (int i = 0; i != chas.length; i++) { 16 | if (chas[i] == '0') { 17 | count++; 18 | start = start == -1 ? i : start; 19 | } else { 20 | if (count == k) { 21 | while (count-- != 0) 22 | chas[start++] = 0; 23 | } 24 | count = 0; 25 | start = -1; 26 | } 27 | } 28 | if (count == k) { 29 | while (count-- != 0) 30 | chas[start++] = 0; 31 | } 32 | return String.valueOf(chas); 33 | } 34 | 35 | public static void main(String[] args) { 36 | String test1 = "0A0B0C00D0"; 37 | System.out.println(removeKZeros(test1, 1)); 38 | 39 | String test2 = "00A00B0C00D0"; 40 | System.out.println(removeKZeros(test2, 2)); 41 | 42 | String test3 = "000A00B000C0D00"; 43 | System.out.println(removeKZeros(test3, 3)); 44 | 45 | String test4 = "0000A0000B00C000D0000"; 46 | System.out.println(removeKZeros(test4, 4)); 47 | 48 | String test5 = "00000000"; 49 | System.out.println(removeKZeros(test5, 5)); 50 | 51 | } 52 | 53 | } 54 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1004.md: -------------------------------------------------------------------------------- 1 | ## 判断两个字符串是否互为旋转词 2 | 3 | **题目:** 4 | >如果一个字符串str,把字符串str前面任意的部分挪到后面形成的字符串叫作str的旋转词。 5 | 6 | ```java 7 | public class Problem_04_IsRotation { 8 | 9 | public static boolean isRotation(String a, String b) { 10 | if (a == null || b == null || a.length() != b.length()) { 11 | return false; 12 | } 13 | String b2 = b + b; 14 | return getIndexOf(b2, a) != -1; 15 | } 16 | 17 | // KMP Algorithm 18 | public static int getIndexOf(String s, String m) { 19 | if (s.length() < m.length()) { 20 | return -1; 21 | } 22 | char[] ss = s.toCharArray(); 23 | char[] ms = m.toCharArray(); 24 | int si = 0; 25 | int mi = 0; 26 | int[] next = getNextArray(ms); 27 | while (si < ss.length && mi < ms.length) { 28 | if (ss[si] == ms[mi]) { 29 | si++; 30 | mi++; 31 | } else if (next[mi] == -1) { 32 | si++; 33 | } else { 34 | mi = next[mi]; 35 | } 36 | } 37 | return mi == ms.length ? si - mi : -1; 38 | } 39 | 40 | public static int[] getNextArray(char[] ms) { 41 | if (ms.length == 1) { 42 | return new int[] { -1 }; 43 | } 44 | int[] next = new int[ms.length]; 45 | next[0] = -1; 46 | next[1] = 0; 47 | int pos = 2; 48 | int cn = 0; 49 | while (pos < next.length) { 50 | if (ms[pos - 1] == ms[cn]) { 51 | next[pos++] = ++cn; 52 | } else if (cn > 0) { 53 | cn = next[cn]; 54 | } else { 55 | next[pos++] = 0; 56 | } 57 | } 58 | return next; 59 | } 60 | 61 | public static void main(String[] args) { 62 | String str1 = "yunzuocheng"; 63 | String str2 = "zuochengyun"; 64 | System.out.println(isRotation(str1, str2)); 65 | 66 | } 67 | 68 | } 69 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1005.md: -------------------------------------------------------------------------------- 1 | ## 将整数字符串转成整数值 2 | 3 | **题目:** 4 | >给定一个字符串str,如果str符合日常书写的整数形式,并且属于32位整数的范围,返回str所代表的整数值,否则返回0。 5 | ``` 6 | 7 | 8 | ```java 9 | public class Problem_05_ConvertStringToInteger { 10 | 11 | public static int convert(String str) { 12 | if (str == null || str.equals("")) { 13 | return 0; // can not convert 14 | } 15 | char[] chas = str.toCharArray(); 16 | if (!isValid(chas)) { 17 | return 0; // can not convert 18 | } 19 | boolean posi = chas[0] == '-' ? false : true; 20 | int minq = Integer.MIN_VALUE / 10; 21 | int minr = Integer.MIN_VALUE % 10; 22 | int res = 0; 23 | int cur = 0; 24 | for (int i = posi ? 0 : 1; i < chas.length; i++) { 25 | cur = '0' - chas[i]; 26 | if ((res < minq) || (res == minq && cur < minr)) { 27 | return 0; // can not convert 28 | } 29 | res = res * 10 + cur; 30 | } 31 | if (posi && res == Integer.MIN_VALUE) { 32 | return 0; // can not convert 33 | } 34 | return posi ? -res : res; 35 | } 36 | 37 | public static boolean isValid(char[] chas) { 38 | if (chas[0] != '-' && (chas[0] < '0' || chas[0] > '9')) { 39 | return false; 40 | } 41 | if (chas[0] == '-' && (chas.length == 1 || chas[1] == '0')) { 42 | return false; 43 | } 44 | if (chas[0] == '0' && chas.length > 1) { 45 | return false; 46 | } 47 | for (int i = 1; i < chas.length; i++) { 48 | if (chas[i] < '0' || chas[i] > '9') { 49 | return false; 50 | } 51 | } 52 | return true; 53 | } 54 | 55 | public static void main(String[] args) { 56 | String test1 = "2147483647"; // max in java 57 | System.out.println(convert(test1)); 58 | 59 | String test2 = "-2147483648"; // min in java 60 | System.out.println(convert(test2)); 61 | 62 | String test3 = "2147483648"; // overflow 63 | System.out.println(convert(test3)); 64 | 65 | String test4 = "-2147483649"; // overflow 66 | System.out.println(convert(test4)); 67 | 68 | String test5 = "-123"; 69 | System.out.println(convert(test5)); 70 | 71 | } 72 | 73 | } 74 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1006.md: -------------------------------------------------------------------------------- 1 | ## 替换字符串中连续出现的指定字符串 2 | 3 | **题目:** 4 | >给定三个字符串str、from和to,把str中所有from的子串全部替换成to字符串,对连续出现from的部分要求只替换成一个to字符串,返回最终的结果字符串。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_06_ReplaceString { 10 | 11 | public static String replace(String str, String from, String to) { 12 | if (str == null || from == null || str.equals("") || from.equals("")) { 13 | return str; 14 | } 15 | char[] chas = str.toCharArray(); 16 | char[] chaf = from.toCharArray(); 17 | int match = 0; 18 | for (int i = 0; i < chas.length; i++) { 19 | if (chas[i] == chaf[match++]) { 20 | if (match == chaf.length) { 21 | clear(chas, i, chaf.length); 22 | match = 0; 23 | } 24 | } else { 25 | if (chas[i] == chaf[0]) { 26 | i--; 27 | } 28 | match = 0; 29 | } 30 | } 31 | String res = ""; 32 | String cur = ""; 33 | for (int i = 0; i < chas.length; i++) { 34 | if (chas[i] != 0) { 35 | cur = cur + String.valueOf(chas[i]); 36 | } 37 | if (chas[i] == 0 && (i == 0 || chas[i - 1] != 0)) { 38 | res = res + cur + to; 39 | cur = ""; 40 | } 41 | } 42 | if (!cur.equals("")) { 43 | res = res + cur; 44 | } 45 | return res; 46 | } 47 | 48 | public static void clear(char[] chas, int end, int len) { 49 | while (len-- != 0) { 50 | chas[end--] = 0; 51 | } 52 | } 53 | 54 | public static void main(String[] args) { 55 | String str = "abc1abcabc1234abcabcabc5678"; 56 | String from = "abc"; 57 | String to = "XXXXX"; 58 | System.out.println(replace(str, from, to)); 59 | 60 | str = "abc"; 61 | from = "123"; 62 | to = "X"; 63 | System.out.println(replace(str, from, to)); 64 | 65 | } 66 | 67 | } 68 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1007.md: -------------------------------------------------------------------------------- 1 | ## 字符串的统计字符串 2 | 3 | **题目:** 4 | >给定一个字符串str,返回str的统计宇符串。例如,"aabbadddffc"的统计字符串为"a_3_b_2_a_l_d_3_f_2_c_l"。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_07_ConvertStringToCount { 10 | 11 | public static String getCountString(String str) { 12 | if (str == null || str.equals("")) { 13 | return ""; 14 | } 15 | char[] chs = str.toCharArray(); 16 | String res = String.valueOf(chs[0]); 17 | int num = 1; 18 | for (int i = 1; i < chs.length; i++) { 19 | if (chs[i] != chs[i - 1]) { 20 | res = concat(res, String.valueOf(num), String.valueOf(chs[i])); 21 | num = 1; 22 | } else { 23 | num++; 24 | } 25 | } 26 | return concat(res, String.valueOf(num), ""); 27 | } 28 | 29 | public static String concat(String s1, String s2, String s3) { 30 | return s1 + "_" + s2 + (s3.equals("") ? s3 : "_" + s3); 31 | } 32 | 33 | public static char getCharAt(String cstr, int index) { 34 | if (cstr == null || cstr.equals("")) { 35 | return 0; 36 | } 37 | char[] chs = cstr.toCharArray(); 38 | boolean stage = true; 39 | char cur = 0; 40 | int num = 0; 41 | int sum = 0; 42 | for (int i = 0; i != chs.length; i++) { 43 | if (chs[i] == '_') { 44 | stage = !stage; 45 | } else if (stage) { 46 | sum += num; 47 | if (sum > index) { 48 | return cur; 49 | } 50 | num = 0; 51 | cur = chs[i]; 52 | } else { 53 | num = num * 10 + chs[i] - '0'; 54 | } 55 | } 56 | return sum + num > index ? cur : 0; 57 | } 58 | 59 | public static void main(String[] args) { 60 | String str = "aaabbadddffc"; 61 | String res = getCountString(str); 62 | System.out.println(str); 63 | System.out.println(res); 64 | System.out.print(getCharAt(res, 9)); 65 | 66 | } 67 | 68 | } 69 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1009.md: -------------------------------------------------------------------------------- 1 | ## 在有序但含有空的数组中查找字符串 2 | 3 | **题目:** 4 | >给定一个字符串数组strs[],在strs中有些位置为null,但在不为null的位置上,其字符串是按照字典顺序由小到大依次出现的。再给定一个字符串str,请返回str在strs中出现的最左的位置。 5 | 6 | 7 | ```java 8 | public class Problem_09_FindStringInContainsNullArray { 9 | 10 | public static int getIndex(String[] strs, String str) { 11 | if (strs == null || strs.length == 0 || str == null) { 12 | return -1; 13 | } 14 | int res = -1; 15 | int left = 0; 16 | int right = strs.length - 1; 17 | int mid = 0; 18 | int i = 0; 19 | while (left <= right) { 20 | mid = (left + right) / 2; 21 | if (strs[mid] != null && strs[mid].equals(str)) { 22 | res = mid; 23 | right = mid - 1; 24 | } else if (strs[mid] != null) { 25 | if (strs[mid].compareTo(str) < 0) { 26 | left = mid + 1; 27 | } else { 28 | right = mid - 1; 29 | } 30 | } else { 31 | i = mid; 32 | while (strs[i] == null && --i >= left) 33 | ; 34 | if (i < left || strs[i].compareTo(str) < 0) { 35 | left = mid + 1; 36 | } else { 37 | res = strs[i].equals(str) ? i : res; 38 | right = i - 1; 39 | } 40 | } 41 | } 42 | return res; 43 | } 44 | 45 | public static void main(String[] args) { 46 | String[] strs = new String[] { null, "a", null, "a", null, "b", null, 47 | null, null, "b", null, "c", null, "c", null, null, "d", null, 48 | null, null, null, null, "d", null, "e", null, null, "e", null, 49 | null, null, "f", null, "f", null }; 50 | String str1 = "a"; 51 | System.out.println(getIndex(strs, str1)); 52 | String str2 = "b"; 53 | System.out.println(getIndex(strs, str2)); 54 | String str3 = "c"; 55 | System.out.println(getIndex(strs, str3)); 56 | String str4 = "d"; 57 | System.out.println(getIndex(strs, str4)); 58 | String str5 = "e"; 59 | System.out.println(getIndex(strs, str5)); 60 | String str6 = "f"; 61 | System.out.println(getIndex(strs, str6)); 62 | 63 | } 64 | 65 | } 66 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1010.md: -------------------------------------------------------------------------------- 1 | ## 字符串的调整与替换 2 | 3 | **题目:** 4 | >给定一个字符类型的数组chas[],chas右半区全是空字符,左半区不含有空字符。现在想将左半区中所有的空格字符替换成”%20”,假设chas右半区足够大,可以满足替换所需要的空间,请完成替换函数。 5 | 6 | 7 | ```java 8 | public class Problem_10_ModifyAndReplace { 9 | 10 | public static void replace(char[] chas) { 11 | if (chas == null || chas.length == 0) { 12 | return; 13 | } 14 | int num = 0; 15 | int len = 0; 16 | for (len = 0; len < chas.length && chas[len] != 0; len++) { 17 | if (chas[len] == ' ') { 18 | num++; 19 | } 20 | } 21 | int j = len + num * 2 - 1; 22 | for (int i = len - 1; i > -1; i--) { 23 | if (chas[i] != ' ') { 24 | chas[j--] = chas[i]; 25 | } else { 26 | chas[j--] = '0'; 27 | chas[j--] = '2'; 28 | chas[j--] = '%'; 29 | } 30 | } 31 | } 32 | 33 | public static void modify(char[] chas) { 34 | if (chas == null || chas.length == 0) { 35 | return; 36 | } 37 | int j = chas.length - 1; 38 | for (int i = chas.length - 1; i > -1; i--) { 39 | if (chas[i] != '*') { 40 | chas[j--] = chas[i]; 41 | } 42 | } 43 | for (; j > -1;) { 44 | chas[j--] = '*'; 45 | } 46 | } 47 | 48 | public static void main(String[] args) { 49 | char[] chas1 = { 'a', ' ', 'b', ' ', ' ', 'c', 0, 0, 0, 0, 0, 0, 0, 0, }; 50 | replace(chas1); 51 | System.out.println(String.valueOf(chas1)); 52 | 53 | char[] chas2 = { '1', '2', '*', '*', '3', '4', '5' }; 54 | modify(chas2); 55 | System.out.println(String.valueOf(chas2)); 56 | 57 | } 58 | 59 | } 60 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1014.md: -------------------------------------------------------------------------------- 1 | ## 括号字符串的有效性和最长有效长度 2 | 3 | **题目:** 4 | >给定一个字符串str,判断是不是整体有效的括号字符串。 5 | 6 | 7 | ```java 8 | public class Problem_14_ParenthesesProblem { 9 | 10 | public static boolean isValid(String str) { 11 | if (str == null || str.equals("")) { 12 | return false; 13 | } 14 | char[] chas = str.toCharArray(); 15 | int status = 0; 16 | for (int i = 0; i < chas.length; i++) { 17 | if (chas[i] != ')' && chas[i] != '(') { 18 | return false; 19 | } 20 | if (chas[i] == ')' && --status < 0) { 21 | return false; 22 | } 23 | if (chas[i] == '(') { 24 | status++; 25 | } 26 | } 27 | return status == 0; 28 | } 29 | 30 | public static int maxLength(String str) { 31 | if (str == null || str.equals("")) { 32 | return 0; 33 | } 34 | char[] chas = str.toCharArray(); 35 | int[] dp = new int[chas.length]; 36 | int pre = 0; 37 | int res = 0; 38 | for (int i = 1; i < chas.length; i++) { 39 | if (chas[i] == ')') { 40 | pre = i - dp[i - 1] - 1; 41 | if (pre >= 0 && chas[pre] == '(') { 42 | dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0); 43 | } 44 | } 45 | res = Math.max(res, dp[i]); 46 | } 47 | return res; 48 | } 49 | 50 | public static void main(String[] args) { 51 | String str1 = "((())())"; 52 | System.out.println(isValid(str1)); 53 | System.out.println(maxLength(str1)); 54 | 55 | String str2 = "(())(()(()))"; 56 | System.out.println(isValid(str2)); 57 | System.out.println(maxLength(str2)); 58 | 59 | String str3 = "()(()()("; 60 | System.out.println(isValid(str3)); 61 | System.out.println(maxLength(str3)); 62 | 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1015.md: -------------------------------------------------------------------------------- 1 | ## 公式字符串求值 2 | 3 | **题目:** 4 | >给定一个字符串str,str表示一个公式,公式里可能有整数、加减乘除符号和左右括号,返回公式的计算结果。 5 | 6 | 7 | 8 | ```java 9 | import java.util.LinkedList; 10 | 11 | public class Problem_15_ExpressionCompute { 12 | 13 | public static int getValue(String str) { 14 | return value(str.toCharArray(), 0)[0]; 15 | } 16 | 17 | public static int[] value(char[] str, int i) { 18 | LinkedList que = new LinkedList(); 19 | int pre = 0; 20 | int[] bra = null; 21 | while (i < str.length && str[i] != ')') { 22 | if (str[i] >= '0' && str[i] <= '9') { 23 | pre = pre * 10 + str[i++] - '0'; 24 | } else if (str[i] != '(') { 25 | addNum(que, pre); 26 | que.addLast(String.valueOf(str[i++])); 27 | pre = 0; 28 | } else { 29 | bra = value(str, i + 1); 30 | pre = bra[0]; 31 | i = bra[1] + 1; 32 | } 33 | } 34 | addNum(que, pre); 35 | return new int[] { getNum(que), i }; 36 | } 37 | 38 | public static void addNum(LinkedList que, int num) { 39 | if (!que.isEmpty()) { 40 | int cur = 0; 41 | String top = que.pollLast(); 42 | if (top.equals("+") || top.equals("-")) { 43 | que.addLast(top); 44 | } else { 45 | cur = Integer.valueOf(que.pollLast()); 46 | num = top.equals("*") ? (cur * num) : (cur / num); 47 | } 48 | } 49 | que.addLast(String.valueOf(num)); 50 | } 51 | 52 | public static int getNum(LinkedList que) { 53 | int res = 0; 54 | boolean add = true; 55 | String cur = null; 56 | int num = 0; 57 | while (!que.isEmpty()) { 58 | cur = que.pollFirst(); 59 | if (cur.equals("+")) { 60 | add = true; 61 | } else if (cur.equals("-")) { 62 | add = false; 63 | } else { 64 | num = Integer.valueOf(cur); 65 | res += add ? num : (-num); 66 | } 67 | } 68 | return res; 69 | } 70 | 71 | public static void main(String[] args) { 72 | String exp = "48*((70-65)-43)+8*1"; 73 | System.out.println(getValue(exp)); 74 | 75 | exp = "4*(6+78)+53-9/2+45*8"; 76 | System.out.println(getValue(exp)); 77 | 78 | exp = "10-5*3"; 79 | System.out.println(getValue(exp)); 80 | 81 | exp = "-3*4"; 82 | System.out.println(getValue(exp)); 83 | 84 | exp = "3+1*4"; 85 | System.out.println(getValue(exp)); 86 | 87 | } 88 | 89 | } 90 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1016.md: -------------------------------------------------------------------------------- 1 | ## 0左边必有1的二进制字符串数量 2 | 3 | **题目:** 4 | >给定一个整数N,求由"0"字符与"1"字符组成的长度为N的所有字符串中,满足"0"字符的左边必有"1"字符的字符串数量。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_16_ZeroLeftOneStringNumber { 10 | 11 | public static int getNum1(int n) { 12 | if (n < 1) { 13 | return 0; 14 | } 15 | return process(1, n); 16 | } 17 | 18 | public static int process(int i, int n) { 19 | if (i == n - 1) { 20 | return 2; 21 | } 22 | if (i == n) { 23 | return 1; 24 | } 25 | return process(i + 1, n) + process(i + 2, n); 26 | } 27 | 28 | public static int getNum2(int n) { 29 | if (n < 1) { 30 | return 0; 31 | } 32 | if (n == 1) { 33 | return 1; 34 | } 35 | int pre = 1; 36 | int cur = 1; 37 | int tmp = 0; 38 | for (int i = 2; i < n + 1; i++) { 39 | tmp = cur; 40 | cur += pre; 41 | pre = tmp; 42 | } 43 | return cur; 44 | } 45 | 46 | public static int getNum3(int n) { 47 | if (n < 1) { 48 | return 0; 49 | } 50 | if (n == 1 || n == 2) { 51 | return n; 52 | } 53 | int[][] base = { { 1, 1 }, { 1, 0 } }; 54 | int[][] res = matrixPower(base, n - 2); 55 | return 2 * res[0][0] + res[1][0]; 56 | } 57 | 58 | public static int[][] matrixPower(int[][] m, int p) { 59 | int[][] res = new int[m.length][m[0].length]; 60 | for (int i = 0; i < res.length; i++) { 61 | res[i][i] = 1; 62 | } 63 | int[][] tmp = m; 64 | for (; p != 0; p >>= 1) { 65 | if ((p & 1) != 0) { 66 | res = muliMatrix(res, tmp); 67 | } 68 | tmp = muliMatrix(tmp, tmp); 69 | } 70 | return res; 71 | } 72 | 73 | public static int[][] muliMatrix(int[][] m1, int[][] m2) { 74 | int[][] res = new int[m1.length][m2[0].length]; 75 | for (int i = 0; i < m1.length; i++) { 76 | for (int j = 0; j < m2[0].length; j++) { 77 | for (int k = 0; k < m2.length; k++) { 78 | res[i][j] += m1[i][k] * m2[k][j]; 79 | } 80 | } 81 | } 82 | return res; 83 | } 84 | 85 | public static void main(String[] args) { 86 | for (int i = 0; i != 20; i++) { 87 | System.out.println(getNum1(i)); 88 | System.out.println(getNum2(i)); 89 | System.out.println(getNum3(i)); 90 | System.out.println("==================="); 91 | } 92 | 93 | } 94 | } 95 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1017.md: -------------------------------------------------------------------------------- 1 | ## 拼接所有字符串产生字典顺序最小的大写字符串 2 | 3 | **题目:** 4 | >给定一个字符串类型的数组strs,请找到一种拼接顺序,使得将所有的字符串拼接起来组成的大写字符串是所有可能性中字典顺序最小的,井返回这个大写字符串。 5 | 6 | 7 | 8 | 9 | ```java 10 | import java.util.Arrays; 11 | import java.util.Comparator; 12 | 13 | public class Problem_17_LowestLexicography { 14 | 15 | public static class MyComparator implements Comparator { 16 | @Override 17 | public int compare(String a, String b) { 18 | return (a + b).compareTo(b + a); 19 | } 20 | } 21 | 22 | public static String lowestString(String[] strs) { 23 | if (strs == null || strs.length == 0) { 24 | return ""; 25 | } 26 | // 根据新的比较方式排序 27 | Arrays.sort(strs, new MyComparator()); 28 | String res = ""; 29 | for (int i = 0; i < strs.length; i++) { 30 | res += strs[i]; 31 | } 32 | return res; 33 | } 34 | 35 | public static void main(String[] args) { 36 | String[] strs1 = { "jibw", "ji", "jp", "bw", "jibw" }; 37 | System.out.println(lowestString(strs1)); 38 | 39 | String[] strs2 = { "ba", "b" }; 40 | System.out.println(lowestString(strs2)); 41 | 42 | } 43 | 44 | } 45 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1018.md: -------------------------------------------------------------------------------- 1 | ## 找到宇符串的最长无重复字符子串 2 | 3 | **题目:** 4 | >给定一个字符串str,返回str的最长无重复字符子串的长度。 5 | 6 | 7 | ```java 8 | public class Problem_18_LongestNoRepeatSubstring { 9 | 10 | public static int maxUnique(String str) { 11 | if (str == null || str.equals("")) { 12 | return 0; 13 | } 14 | char[] chas = str.toCharArray(); 15 | int[] map = new int[256]; 16 | for (int i = 0; i < 256; i++) { 17 | map[i] = -1; 18 | } 19 | int len = 0; 20 | int pre = -1; 21 | int cur = 0; 22 | for (int i = 0; i != chas.length; i++) { 23 | pre = Math.max(pre, map[chas[i]]); 24 | cur = i - pre; 25 | len = Math.max(len, cur); 26 | map[chas[i]] = i; 27 | } 28 | return len; 29 | } 30 | 31 | // for test 32 | public static String getRandomString(int len) { 33 | char[] str = new char[len]; 34 | int base = 'a'; 35 | int range = 'z' - 'a' + 1; 36 | for (int i = 0; i != len; i++) { 37 | str[i] = (char) ((int) (Math.random() * range) + base); 38 | } 39 | return String.valueOf(str); 40 | } 41 | 42 | // for test 43 | public static String maxUniqueString(String str) { 44 | if (str == null || str.equals("")) { 45 | return str; 46 | } 47 | char[] chas = str.toCharArray(); 48 | int[] map = new int[256]; 49 | for (int i = 0; i < 256; i++) { 50 | map[i] = -1; 51 | } 52 | int len = -1; 53 | int pre = -1; 54 | int cur = 0; 55 | int end = -1; 56 | for (int i = 0; i != chas.length; i++) { 57 | pre = Math.max(pre, map[chas[i]]); 58 | cur = i - pre; 59 | if (cur > len) { 60 | len = cur; 61 | end = i; 62 | } 63 | map[chas[i]] = i; 64 | } 65 | return str.substring(end - len + 1, end + 1); 66 | } 67 | 68 | public static void main(String[] args) { 69 | String str = getRandomString(20); 70 | System.out.println(str); 71 | System.out.println(maxUnique(str)); 72 | System.out.println(maxUniqueString(str)); 73 | } 74 | } 75 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1019.md: -------------------------------------------------------------------------------- 1 | ## 找到被指的新类型字符 2 | 3 | **题目:** 4 | >新类型字符的定义如下: 5 | 1.新类型字符是长度为1;或者2的字符串。 6 | 2.表现形式可以仅是小写字母,例如,”e”;也可以是大写字母+小写字母例如,”Ab”;还可以是大写字母+大写字母,例如,DC”。 7 | 现在给定一个字符串str,由一定是若干新类型字符正确组合的结果。比如”eaCCBi”,出新类型字符”e”、”a”、”cc"和”Bi”拼成。再给定一个整数k,代表str中的位置。请返回被k位置指中的新类型字符。 8 | 9 | ```java 10 | public class Problem_19_FindNewTypeChar { 11 | 12 | public static String pointNewchar(String s, int k) { 13 | if (s == null || s.equals("") || k < 0 || k >= s.length()) { 14 | return ""; 15 | } 16 | char[] chas = s.toCharArray(); 17 | int uNum = 0; 18 | for (int i = k - 1; i >= 0; i--) { 19 | if (!isUpper(chas[i])) { 20 | break; 21 | } 22 | uNum++; 23 | } 24 | if ((uNum & 1) == 1) { 25 | return s.substring(k - 1, k + 1); 26 | } 27 | if (isUpper(chas[k])) { 28 | return s.substring(k, k + 2); 29 | } 30 | return String.valueOf(chas[k]); 31 | } 32 | 33 | public static boolean isUpper(char ch) { 34 | return !(ch < 'A' || ch > 'Z'); 35 | } 36 | 37 | public static void main(String[] args) { 38 | String str = "aaABCDEcBCg"; 39 | System.out.println(pointNewchar(str, 7)); 40 | System.out.println(pointNewchar(str, 4)); 41 | System.out.println(pointNewchar(str, 10)); 42 | 43 | } 44 | 45 | } 46 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1020.md: -------------------------------------------------------------------------------- 1 | ## 最小包含子串的长度 2 | 3 | **题目:** 4 | >给定字符串strl和str2,求strl的子串中含有str2所有字符的最小子串长度。 5 | 6 | 7 | ```java 8 | public class Problem_20_MinWindowLength { 9 | 10 | public static int minLength(String str1, String str2) { 11 | if (str1 == null || str2 == null || str1.length() < str2.length()) { 12 | return 0; 13 | } 14 | char[] chas1 = str1.toCharArray(); 15 | char[] chas2 = str2.toCharArray(); 16 | int[] map = new int[256]; 17 | for (int i = 0; i != chas2.length; i++) { 18 | map[chas2[i]]++; 19 | } 20 | int left = 0; 21 | int right = 0; 22 | int match = chas2.length; 23 | int minLen = Integer.MAX_VALUE; 24 | while (right != chas1.length) { 25 | map[chas1[right]]--; 26 | if (map[chas1[right]] >= 0) { 27 | match--; 28 | } 29 | if (match == 0) { 30 | while (map[chas1[left]] < 0) { 31 | map[chas1[left++]]++; 32 | } 33 | minLen = Math.min(minLen, right - left + 1); 34 | match++; 35 | map[chas1[left++]]++; 36 | } 37 | right++; 38 | } 39 | return minLen == Integer.MAX_VALUE ? 0 : minLen; 40 | } 41 | 42 | public static void main(String[] args) { 43 | String str1 = "adabbca"; 44 | String str2 = "acb"; 45 | System.out.println(minLength(str1, str2)); 46 | 47 | } 48 | 49 | } 50 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter05_String/Q1021.md: -------------------------------------------------------------------------------- 1 | ## 回文最少分割数 2 | 3 | **题目:** 4 | >给定一个字符串str,返回把str全部切成回文子串的最小分割数。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_21_PalindromeMinCut { 10 | 11 | public static int minCut(String str) { 12 | if (str == null || str.equals("")) { 13 | return 0; 14 | } 15 | char[] chas = str.toCharArray(); 16 | int len = chas.length; 17 | int[] dp = new int[len + 1]; 18 | dp[len] = -1; 19 | boolean[][] p = new boolean[len][len]; 20 | for (int i = len - 1; i >= 0; i--) { 21 | dp[i] = Integer.MAX_VALUE; 22 | for (int j = i; j < len; j++) { 23 | if (chas[i] == chas[j] && (j - i < 2 || p[i + 1][j - 1])) { 24 | p[i][j] = true; 25 | dp[i] = Math.min(dp[i], dp[j + 1] + 1); 26 | } 27 | } 28 | } 29 | return dp[0]; 30 | } 31 | 32 | // for test 33 | public static String getRandomStringOnlyAToD(int len) { 34 | int range = 'D' - 'A' + 1; 35 | char[] charArr = new char[(int) (Math.random() * (len + 1))]; 36 | for (int i = 0; i != charArr.length; i++) { 37 | charArr[i] = (char) ((int) (Math.random() * range) + 'A'); 38 | } 39 | return String.valueOf(charArr); 40 | } 41 | 42 | public static void main(String[] args) { 43 | int maxLen = 10; 44 | int testTimes = 5; 45 | String str = null; 46 | for (int i = 0; i != testTimes; i++) { 47 | str = getRandomStringOnlyAToD(maxLen); 48 | System.out.print("\"" + str + "\"" + " : "); 49 | System.out.println(minCut(str)); 50 | } 51 | 52 | } 53 | } 54 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter06_Bit/Q1001.md: -------------------------------------------------------------------------------- 1 | ## 不用额外变量交换两个整数的值 2 | 3 | **题目:** 4 | >如何不用任何额外变量交换两个整数的值? 5 | 6 | ```java 7 | public class Problem_01_SwapWithoutTmp { 8 | 9 | public static void main(String[] args) { 10 | int a = 16; 11 | int b = 111; 12 | System.out.println(a); 13 | System.out.println(b); 14 | a = a ^ b; 15 | b = a ^ b; 16 | a = a ^ b; 17 | System.out.println(a); 18 | System.out.println(b); 19 | } 20 | 21 | } 22 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter06_Bit/Q1002.md: -------------------------------------------------------------------------------- 1 | ## 不用任何比较判断找出两个数中较大的数 2 | 3 | **题目:** 4 | >给定两个32位整数a和b,返回a和b中较大的。 5 | 6 | 7 | ```java 8 | public class Problem_02_GetMax { 9 | 10 | public static int flip(int n) { 11 | return n ^ 1; 12 | } 13 | 14 | public static int sign(int n) { 15 | return flip((n >> 31) & 1); 16 | } 17 | 18 | public static int getMax1(int a, int b) { 19 | int c = a - b; 20 | int scA = sign(c); 21 | int scB = flip(scA); 22 | return a * scA + b * scB; 23 | } 24 | 25 | public static int getMax2(int a, int b) { 26 | int c = a - b; 27 | int sa = sign(a); 28 | int sb = sign(b); 29 | int sc = sign(c); 30 | int difSab = sa ^ sb; 31 | int sameSab = flip(difSab); 32 | int returnA = difSab * sa + sameSab * sc; 33 | int returnB = flip(returnA); 34 | return a * returnA + b * returnB; 35 | } 36 | 37 | public static void main(String[] args) { 38 | int a = -16; 39 | int b = 1; 40 | System.out.println(getMax1(a, b)); 41 | System.out.println(getMax2(a, b)); 42 | a = 2147483647; 43 | b = -2147480000; 44 | System.out.println(getMax1(a, b)); // wrong answer because of overflow 45 | System.out.println(getMax2(a, b)); 46 | 47 | } 48 | 49 | } 50 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter06_Bit/Q1004.md: -------------------------------------------------------------------------------- 1 | ## 整数的二进制表达中有多少个1 2 | 3 | **题目:** 4 | >给定一个32位整数n,可为0,可为正,也可以为负,返回该整数二进制表达中1的个数。 5 | 6 | ```java 7 | public class Problem_04_NumberOf1 { 8 | 9 | public static int count1(int n) { 10 | int res = 0; 11 | while (n != 0) { 12 | res += n & 1; 13 | n >>>= 1; 14 | } 15 | return res; 16 | } 17 | 18 | public static int count2(int n) { 19 | int res = 0; 20 | while (n != 0) { 21 | n &= (n - 1); 22 | res++; 23 | } 24 | return res; 25 | } 26 | 27 | public static int count3(int n) { 28 | int res = 0; 29 | while (n != 0) { 30 | n -= n & (~n + 1); 31 | res++; 32 | } 33 | return res; 34 | } 35 | 36 | public static int count4(int n) { 37 | n = (n & 0x55555555) + ((n >>> 1) & 0x55555555); 38 | n = (n & 0x33333333) + ((n >>> 2) & 0x33333333); 39 | n = (n & 0x0f0f0f0f) + ((n >>> 4) & 0x0f0f0f0f); 40 | n = (n & 0x00ff00ff) + ((n >>> 8) & 0x00ff00ff); 41 | n = (n & 0x0000ffff) + ((n >>> 16) & 0x0000ffff); 42 | return n; 43 | } 44 | 45 | public static void printNumBit(int n) { 46 | for (int i = 31; i != -1; i--) { 47 | if ((n & (1 << i)) != 0) { 48 | System.out.print(1); 49 | } else { 50 | System.out.print(0); 51 | } 52 | } 53 | System.out.println(); 54 | } 55 | 56 | public static void main(String[] args) { 57 | int num = -1; 58 | System.out.println(count1(num)); 59 | System.out.println(count2(num)); 60 | System.out.println(count3(num)); 61 | System.out.println(count4(num)); 62 | printNumBit(0x55555555); 63 | printNumBit(0x33333333); 64 | printNumBit(0x0f0f0f0f); 65 | printNumBit(0x00ff00ff); 66 | printNumBit(0x0000ffff); 67 | 68 | } 69 | 70 | } 71 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter06_Bit/Q1005.md: -------------------------------------------------------------------------------- 1 | ## 在其他数都出现偶数次的数组中找到出现奇数次的数 2 | 3 | **题目:** 4 | >给定一个整型数组arr,其中只有一个数出现了奇数次,其他的数都出现了偶数次,打印这个敛。 5 | 6 | ```java 7 | public class Problem_05_EvenTimesOddTimes { 8 | 9 | public static void printOddTimesNum1(int[] arr) { 10 | int eO = 0; 11 | for (int cur : arr) { 12 | eO ^= cur; 13 | } 14 | System.out.println(eO); 15 | } 16 | 17 | public static void printOddTimesNum2(int[] arr) { 18 | int eO = 0, eOhasOne = 0; 19 | for (int curNum : arr) { 20 | eO ^= curNum; 21 | } 22 | int rightOne = eO & (~eO + 1); 23 | for (int cur : arr) { 24 | if ((cur & rightOne) != 0) { 25 | eOhasOne ^= cur; 26 | } 27 | } 28 | System.out.println(eOhasOne + " " + (eO ^ eOhasOne)); 29 | } 30 | 31 | public static void main(String[] args) { 32 | int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; 33 | printOddTimesNum1(arr1); 34 | 35 | int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; 36 | printOddTimesNum2(arr2); 37 | 38 | } 39 | 40 | } 41 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter06_Bit/Q1006.md: -------------------------------------------------------------------------------- 1 | ## 在其他数都出现k次的数组中找到只出现一次的数 2 | 3 | 4 | 5 | **题目:** 6 | >给定一个整型数组arr和一个大于1的整数k。已知arr中只有1个数出现了1次,其他的数都出现了k次,请返回只出现了1次的数。 7 | 8 | 9 | 10 | ```java 11 | public class Problem_06_KTimesOneTime { 12 | 13 | public static int onceNum(int[] arr, int k) { 14 | int[] eO = new int[32]; 15 | for (int i = 0; i != arr.length; i++) { 16 | setExclusiveOr(eO, arr[i], k); 17 | } 18 | int res = getNumFromKSysNum(eO, k); 19 | return res; 20 | } 21 | 22 | public static void setExclusiveOr(int[] eO, int value, int k) { 23 | int[] curKSysNum = getKSysNumFromNum(value, k); 24 | for (int i = 0; i != eO.length; i++) { 25 | eO[i] = (eO[i] + curKSysNum[i]) % k; 26 | } 27 | } 28 | 29 | public static int[] getKSysNumFromNum(int value, int k) { 30 | int[] res = new int[32]; 31 | int index = 0; 32 | while (value != 0) { 33 | res[index++] = value % k; 34 | value = value / k; 35 | } 36 | return res; 37 | } 38 | 39 | public static int getNumFromKSysNum(int[] eO, int k) { 40 | int res = 0; 41 | for (int i = eO.length - 1; i != -1; i--) { 42 | res = res * k + eO[i]; 43 | } 44 | return res; 45 | } 46 | 47 | public static void main(String[] args) { 48 | int[] test1 = { 1, 1, 1, 2, 6, 6, 2, 2, 10, 10, 10, 12, 12, 12, 6, 9 }; 49 | System.out.println(onceNum(test1, 3)); 50 | 51 | int[] test2 = { -1, -1, -1, -1, -1, 2, 2, 2, 4, 2, 2 }; 52 | System.out.println(onceNum(test2, 5)); 53 | 54 | } 55 | 56 | } 57 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1001.md: -------------------------------------------------------------------------------- 1 | ## 转圈打印矩阵 2 | 3 | **题目:** 4 | >给定一个整型矩阵matrix,请按照转圈的方式打印它。 5 | 6 | ```java 7 | public class Problem_01_PrintMatrixSpiralOrder { 8 | 9 | public static void spiralOrderPrint(int[][] matrix) { 10 | int tR = 0; 11 | int tC = 0; 12 | int dR = matrix.length - 1; 13 | int dC = matrix[0].length - 1; 14 | while (tR <= dR && tC <= dC) { 15 | printEdge(matrix, tR++, tC++, dR--, dC--); 16 | } 17 | } 18 | 19 | public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) { 20 | if (tR == dR) { // 子矩阵只有一行时 21 | for (int i = tC; i <= dC; i++) { 22 | System.out.print(m[tR][i] + " "); 23 | } 24 | } else if (tC == dC) { // 子矩阵只有一列时 25 | for (int i = tR; i <= dR; i++) { 26 | System.out.print(m[i][tC] + " "); 27 | } 28 | } else { // 一般情况 29 | int curC = tC; 30 | int curR = tR; 31 | while (curC != dC) { 32 | System.out.print(m[tR][curC] + " "); 33 | curC++; 34 | } 35 | while (curR != dR) { 36 | System.out.print(m[curR][dC] + " "); 37 | curR++; 38 | } 39 | while (curC != tC) { 40 | System.out.print(m[dR][curC] + " "); 41 | curC--; 42 | } 43 | while (curR != tR) { 44 | System.out.print(m[curR][tC] + " "); 45 | curR--; 46 | } 47 | } 48 | } 49 | 50 | public static void main(String[] args) { 51 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, 52 | { 13, 14, 15, 16 } }; 53 | spiralOrderPrint(matrix); 54 | 55 | } 56 | 57 | } 58 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1002.md: -------------------------------------------------------------------------------- 1 | ## 将正方形矩阵顺时针转动90° 2 | 3 | **题目:** 4 | >给定一个NxN的矩阵matrix,把这个矩阵调整成顺时针转动90°后的形式。 5 | 6 | 7 | ```java 8 | public class Problem_02_RotateMatrix { 9 | 10 | public static void rotate(int[][] matrix) { 11 | int tR = 0; 12 | int tC = 0; 13 | int dR = matrix.length - 1; 14 | int dC = matrix[0].length - 1; 15 | while (tR < dR) { 16 | rotateEdge(matrix, tR++, tC++, dR--, dC--); 17 | } 18 | } 19 | 20 | public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) { 21 | int times = dC - tC; // times就是总共的组数 22 | int tmp = 0; 23 | for (int i = 0; i != times; i++) { // 一次循环就是一组占据调整 24 | tmp = m[tR][tC + i]; 25 | m[tR][tC + i] = m[dR - i][tC]; 26 | m[dR - i][tC] = m[dR][dC - i]; 27 | m[dR][dC - i] = m[tR + i][dC]; 28 | m[tR + i][dC] = tmp; 29 | } 30 | } 31 | 32 | public static void printMatrix(int[][] matrix) { 33 | for (int i = 0; i != matrix.length; i++) { 34 | for (int j = 0; j != matrix[0].length; j++) { 35 | System.out.print(matrix[i][j] + " "); 36 | } 37 | System.out.println(); 38 | } 39 | } 40 | 41 | public static void main(String[] args) { 42 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, 43 | { 13, 14, 15, 16 } }; 44 | printMatrix(matrix); 45 | rotate(matrix); 46 | System.out.println("========="); 47 | printMatrix(matrix); 48 | 49 | } 50 | 51 | } 52 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1003.md: -------------------------------------------------------------------------------- 1 | ## “之” 字形打印矩阵 2 | 3 | **题目:** 4 | >给定一个矩阵matrix,按照“之”字形的方式打印这个矩阵。 5 | 6 | ```java 7 | public class Problem_03_ZigZagPrintMatrix { 8 | 9 | public static void printMatrixZigZag(int[][] matrix) { 10 | int tR = 0; 11 | int tC = 0; 12 | int dR = 0; 13 | int dC = 0; 14 | int endR = matrix.length - 1; 15 | int endC = matrix[0].length - 1; 16 | boolean fromUp = false; 17 | while (tR != endR + 1) { 18 | printLevel(matrix, tR, tC, dR, dC, fromUp); 19 | tR = tC == endC ? tR + 1 : tR; 20 | tC = tC == endC ? tC : tC + 1; 21 | dC = dR == endR ? dC + 1 : dC; 22 | dR = dR == endR ? dR : dR + 1; 23 | fromUp = !fromUp; 24 | } 25 | System.out.println(); 26 | } 27 | 28 | public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, 29 | boolean f) { 30 | if (f) { 31 | while (tR != dR + 1) { 32 | System.out.print(m[tR++][tC--] + " "); 33 | } 34 | } else { 35 | while (dR != tR - 1) { 36 | System.out.print(m[dR--][dC++] + " "); 37 | } 38 | } 39 | } 40 | 41 | public static void main(String[] args) { 42 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 43 | printMatrixZigZag(matrix); 44 | 45 | } 46 | 47 | } 48 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1005.md: -------------------------------------------------------------------------------- 1 | ## 需要排序的最短子数组长度 2 | 3 | **题目:** 4 | >给定一个无序数组arr,求出需要排序最短子数组长度。 5 | 6 | 7 | ```java 8 | public class Problem_05_MinLengthForSort { 9 | 10 | public static int getMinLength(int[] arr) { 11 | if (arr == null || arr.length < 2) { 12 | return 0; 13 | } 14 | int min = arr[arr.length - 1]; 15 | int noMinIndex = -1; 16 | for (int i = arr.length - 2; i != -1; i--) { 17 | if (arr[i] > min) { 18 | noMinIndex = i; 19 | } else { 20 | min = Math.min(min, arr[i]); 21 | } 22 | } 23 | if (noMinIndex == -1) { 24 | return 0; 25 | } 26 | int max = arr[0]; 27 | int noMaxIndex = -1; 28 | for (int i = 1; i != arr.length; i++) { 29 | if (arr[i] < max) { 30 | noMaxIndex = i; 31 | } else { 32 | max = Math.max(max, arr[i]); 33 | } 34 | } 35 | return noMaxIndex - noMinIndex + 1; 36 | } 37 | 38 | public static void main(String[] args) { 39 | int[] arr = { 1, 2, 4, 7, 10, 11, 7, 12, 6, 7, 16, 18, 19 }; 40 | System.out.println(getMinLength(arr)); 41 | 42 | } 43 | 44 | } 45 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1007.md: -------------------------------------------------------------------------------- 1 | ## 在行列都排好序的矩阵中找数 2 | 3 | **题目:** 4 | >给定一个有N*M的整数矩阵matrix和一个整数K,matrix的每一行和每一列都是排好序的。实现一个函数,判断K是否在matrix中。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_07_FindNumInSortedMatrix { 10 | 11 | public static boolean isContains(int[][] matrix, int K) { 12 | int row = 0; 13 | int col = matrix[0].length - 1; 14 | while (row < matrix.length && col > -1) { 15 | if (matrix[row][col] == K) { 16 | return true; 17 | } else if (matrix[row][col] > K) { 18 | col--; 19 | } else { 20 | row++; 21 | } 22 | } 23 | return false; 24 | } 25 | 26 | public static void main(String[] args) { 27 | int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0 28 | { 10, 12, 13, 15, 16, 17, 18 },// 1 29 | { 23, 24, 25, 26, 27, 28, 29 },// 2 30 | { 44, 45, 46, 47, 48, 49, 50 },// 3 31 | { 65, 66, 67, 68, 69, 70, 71 },// 4 32 | { 96, 97, 98, 99, 100, 111, 122 },// 5 33 | { 166, 176, 186, 187, 190, 195, 200 },// 6 34 | { 233, 243, 321, 341, 356, 370, 380 } // 7 35 | }; 36 | int K = 233; 37 | System.out.println(isContains(matrix, K)); 38 | } 39 | 40 | } 41 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1008.md: -------------------------------------------------------------------------------- 1 | ## 最长的可整合子数组的长度 2 | 3 | **题目:** 4 | >先给出可整合数组的定义。 如果一个数组在排序之后,每相邻两个数差的绝对值都为l,则该数组为可整合数组。例如,[5,3,4,6,2]排序之后为[2,3,4,5,6],符合每相邻两个数差的绝对值都为l,所以这个数组为可整合数组。 5 | >给定一个整型数组arr,请返回其中最大可整合子数组的长度。例如,[5,5,3,2,6,4,3]的最大可整合子数组为[5,3,2,6,4],所以返回5。 6 | 7 | ```java 8 | import java.util.Arrays; 9 | import java.util.HashSet; 10 | 11 | public class Problem_08_LongestIntegratedLength { 12 | 13 | public static int getLIL1(int[] arr) { 14 | if (arr == null || arr.length == 0) { 15 | return 0; 16 | } 17 | int len = 0; 18 | for (int i = 0; i < arr.length; i++) { 19 | for (int j = i; j < arr.length; j++) { 20 | if (isIntegrated(arr, i, j)) { 21 | len = Math.max(len, j - i + 1); 22 | } 23 | } 24 | } 25 | return len; 26 | } 27 | 28 | public static boolean isIntegrated(int[] arr, int left, int right) { 29 | int[] newArr = Arrays.copyOfRange(arr, left, right + 1); // O(N) 30 | Arrays.sort(newArr); // O(N*logN) 31 | for (int i = 1; i < newArr.length; i++) { 32 | if (newArr[i - 1] != newArr[i] - 1) { 33 | return false; 34 | } 35 | } 36 | return true; 37 | } 38 | 39 | public static int getLIL2(int[] arr) { 40 | if (arr == null || arr.length == 0) { 41 | return 0; 42 | } 43 | int len = 0; 44 | int max = 0; 45 | int min = 0; 46 | HashSet set = new HashSet(); // 判断重复 47 | for (int i = 0; i < arr.length; i++) { 48 | max = Integer.MIN_VALUE; 49 | min = Integer.MAX_VALUE; 50 | for (int j = i; j < arr.length; j++) { 51 | if (set.contains(arr[j])) { 52 | break; 53 | } 54 | set.add(arr[j]); 55 | max = Math.max(max, arr[j]); 56 | min = Math.min(min, arr[j]); 57 | if (max - min == j - i) { // 新的检查方式 58 | len = Math.max(len, j - i + 1); 59 | } 60 | } 61 | set.clear(); 62 | } 63 | return len; 64 | } 65 | 66 | public static void main(String[] args) { 67 | int[] arr = { 5, 5, 3, 2, 6, 4, 3 }; 68 | System.out.println(getLIL1(arr)); 69 | System.out.println(getLIL2(arr)); 70 | 71 | } 72 | 73 | } 74 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1009.md: -------------------------------------------------------------------------------- 1 | ## 不重复打印排序数组中相加和为给定值的所有二元组和三元组 2 | 3 | **题目:** 4 | >给定排序数组arr和整数k,不重复打印arr中所有相加和为k的不降序二元组。 5 | 6 | 7 | ```java 8 | public class Problem_09_PrintUniquePairAndTriad { 9 | 10 | public static void printUniquePair(int[] arr, int k) { 11 | if (arr == null || arr.length < 2) { 12 | return; 13 | } 14 | int left = 0; 15 | int right = arr.length - 1; 16 | while (left < right) { 17 | if (arr[left] + arr[right] < k) { 18 | left++; 19 | } else if (arr[left] + arr[right] > k) { 20 | right--; 21 | } else { 22 | if (left == 0 || arr[left - 1] != arr[left]) { 23 | System.out.println(arr[left] + "," + arr[right]); 24 | } 25 | left++; 26 | right--; 27 | } 28 | } 29 | } 30 | 31 | public static void printUniqueTriad(int[] arr, int k) { 32 | if (arr == null || arr.length < 3) { 33 | return; 34 | } 35 | for (int i = 0; i < arr.length - 2; i++) { 36 | if (i == 0 || arr[i] != arr[i - 1]) { 37 | printRest(arr, i, i + 1, arr.length - 1, k - arr[i]); 38 | } 39 | } 40 | } 41 | 42 | public static void printRest(int[] arr, int f, int l, int r, int k) { 43 | while (l < r) { 44 | if (arr[l] + arr[r] < k) { 45 | l++; 46 | } else if (arr[l] + arr[r] > k) { 47 | r--; 48 | } else { 49 | if (l == f + 1 || arr[l - 1] != arr[l]) { 50 | System.out.println(arr[f] + "," + arr[l] + "," + arr[r]); 51 | } 52 | l++; 53 | r--; 54 | } 55 | } 56 | } 57 | 58 | public static void printArray(int[] arr) { 59 | for (int i = 0; i != arr.length; i++) { 60 | System.out.print(arr[i] + " "); 61 | } 62 | System.out.println(); 63 | } 64 | 65 | public static void main(String[] args) { 66 | int sum = 10; 67 | int[] arr1 = { -8, -4, -3, 0, 1, 2, 4, 5, 8, 9 }; 68 | printArray(arr1); 69 | System.out.println("===="); 70 | printUniquePair(arr1, sum); 71 | System.out.println("===="); 72 | printUniqueTriad(arr1, sum); 73 | 74 | } 75 | 76 | } 77 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1010.md: -------------------------------------------------------------------------------- 1 | ## 未排序正数数组中累加和为给定值的最长子数组长度 2 | 3 | **题目:** 4 | >给定一个数组arr,该数组无序,但每个值均为正数,再给定一个正数k。求arr的所有子数组中所有元素相加和为k的最长子数组长度。 5 | 6 | ```java 7 | public class Problem_10_LongestSumSubArrayLengthInPositiveArray { 8 | 9 | public static int getMaxLength(int[] arr, int k) { 10 | if (arr == null || arr.length == 0 || k <= 0) { 11 | return 0; 12 | } 13 | int left = 0; 14 | int right = 0; 15 | int sum = arr[0]; 16 | int len = 0; 17 | while (right < arr.length) { 18 | if (sum == k) { 19 | len = Math.max(len, right - left + 1); 20 | sum -= arr[left++]; 21 | } else if (sum < k) { 22 | right++; 23 | if (right == arr.length) { 24 | break; 25 | } 26 | sum += arr[right]; 27 | } else { 28 | sum -= arr[left++]; 29 | } 30 | } 31 | return len; 32 | } 33 | 34 | public static int[] generatePositiveArray(int size) { 35 | int[] result = new int[size]; 36 | for (int i = 0; i != size; i++) { 37 | result[i] = (int) (Math.random() * 10) + 1; 38 | } 39 | return result; 40 | } 41 | 42 | public static void printArray(int[] arr) { 43 | for (int i = 0; i != arr.length; i++) { 44 | System.out.print(arr[i] + " "); 45 | } 46 | System.out.println(); 47 | } 48 | 49 | public static void main(String[] args) { 50 | int len = 20; 51 | int k = 15; 52 | int[] arr = generatePositiveArray(len); 53 | printArray(arr); 54 | System.out.println(getMaxLength(arr, k)); 55 | 56 | } 57 | 58 | } 59 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1011.md: -------------------------------------------------------------------------------- 1 | ## 未排序数组中累加和为给定值的最长子数组系列问题 2 | 3 | **题目:** 4 | >给定一个无序数组arr,其中元素可正、可负、可0,给定一个整数k。求arr所有的子数组中累加和为k的最长子数组长度。 5 | 6 | ```java 7 | import java.util.HashMap; 8 | 9 | public class Problem_11_LongestSumSubArrayLength { 10 | 11 | public static int maxLength(int[] arr, int k) { 12 | if (arr == null || arr.length == 0) { 13 | return 0; 14 | } 15 | HashMap map = new HashMap(); 16 | map.put(0, -1); // important 17 | int len = 0; 18 | int sum = 0; 19 | for (int i = 0; i < arr.length; i++) { 20 | sum += arr[i]; 21 | if (map.containsKey(sum - k)) { 22 | len = Math.max(i - map.get(sum - k), len); 23 | } 24 | if (!map.containsKey(sum)) { 25 | map.put(sum, i); 26 | } 27 | } 28 | return len; 29 | } 30 | 31 | public static int[] generateArray(int size) { 32 | int[] result = new int[size]; 33 | for (int i = 0; i != size; i++) { 34 | result[i] = (int) (Math.random() * 11) - 5; 35 | } 36 | return result; 37 | } 38 | 39 | public static void printArray(int[] arr) { 40 | for (int i = 0; i != arr.length; i++) { 41 | System.out.print(arr[i] + " "); 42 | } 43 | System.out.println(); 44 | } 45 | 46 | public static void main(String[] args) { 47 | int[] arr = generateArray(20); 48 | printArray(arr); 49 | System.out.println(maxLength(arr, 10)); 50 | 51 | } 52 | 53 | } 54 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1012.md: -------------------------------------------------------------------------------- 1 | ## 未排序数组中累加和小于或等于给定值的最长子数组长度 2 | 3 | **题目:** 4 | >给定一个无序数组arr,其中元素可正、可负、可0,给定一个整数k。求arr所有的子数组中累加和小于或等于k的最长子数组长度。 5 | 6 | ```java 7 | public class Problem_12_LongestLessSumSubArrayLength { 8 | 9 | public static int maxLength(int[] arr, int k) { 10 | int[] h = new int[arr.length + 1]; 11 | int sum = 0; 12 | h[0] = sum; 13 | for (int i = 0; i != arr.length; i++) { 14 | sum += arr[i]; 15 | h[i + 1] = Math.max(sum, h[i]); 16 | } 17 | sum = 0; 18 | int res = 0; 19 | int pre = 0; 20 | int len = 0; 21 | for (int i = 0; i != arr.length; i++) { 22 | sum += arr[i]; 23 | pre = getLessIndex(h, sum - k); 24 | len = pre == -1 ? 0 : i - pre + 1; 25 | res = Math.max(res, len); 26 | } 27 | return res; 28 | } 29 | 30 | public static int getLessIndex(int[] arr, int num) { 31 | int low = 0; 32 | int high = arr.length - 1; 33 | int mid = 0; 34 | int res = -1; 35 | while (low <= high) { 36 | mid = (low + high) / 2; 37 | if (arr[mid] >= num) { 38 | res = mid; 39 | high = mid - 1; 40 | } else { 41 | low = mid + 1; 42 | } 43 | } 44 | return res; 45 | } 46 | 47 | // for test 48 | public static int[] generateRandomArray(int len, int maxValue) { 49 | int[] res = new int[len]; 50 | for (int i = 0; i != res.length; i++) { 51 | res[i] = (int) (Math.random() * maxValue) - (maxValue / 3); 52 | } 53 | return res; 54 | } 55 | 56 | // for test 57 | public static void printArray(int[] arr) { 58 | for (int i = 0; i != arr.length; i++) { 59 | System.out.print(arr[i] + " "); 60 | } 61 | System.out.println(); 62 | } 63 | 64 | public static void main(String[] args) { 65 | int[] arr = { 3, -2, -4, 0, 6 }; 66 | int k = -2; 67 | System.out.println(maxLength(arr, k)); 68 | 69 | } 70 | } 71 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1013.md: -------------------------------------------------------------------------------- 1 | ## 计算数组的小和 2 | 3 | **题目:** 4 | >给定一个数组s,实现函数返回s的小和。 5 | 6 | ```java 7 | public class Problem_13_SmallSum { 8 | 9 | public static int getSmallSum(int[] arr) { 10 | if (arr == null || arr.length == 0) { 11 | return 0; 12 | } 13 | return func(arr, 0, arr.length - 1); 14 | } 15 | 16 | public static int func(int[] s, int l, int r) { 17 | if (l == r) { 18 | return 0; 19 | } 20 | int mid = (l + r) / 2; 21 | return func(s, l, mid) + func(s, mid + 1, r) + merge(s, l, mid, r); 22 | } 23 | 24 | public static int merge(int[] s, int left, int mid, int right) { 25 | int[] h = new int[right - left + 1]; 26 | int hi = 0; 27 | int i = left; 28 | int j = mid + 1; 29 | int smallSum = 0; 30 | while (i <= mid && j <= right) { 31 | if (s[i] <= s[j]) { 32 | smallSum += s[i] * (right - j + 1); 33 | h[hi++] = s[i++]; 34 | } else { 35 | h[hi++] = s[j++]; 36 | } 37 | } 38 | for (; (j < right + 1) || (i < mid + 1); j++, i++) { 39 | h[hi++] = i > mid ? s[j] : s[i]; 40 | } 41 | for (int k = 0; k != h.length; k++) { 42 | s[left++] = h[k]; 43 | } 44 | return smallSum; 45 | } 46 | 47 | public static void swap(int[] arr, int index1, int index2) { 48 | int tmp = arr[index1]; 49 | arr[index1] = arr[index2]; 50 | arr[index2] = tmp; 51 | } 52 | 53 | public static void main(String[] args) { 54 | int[] arr = { 3, 1, 2, 4, 6, 2, 7, 8, 1 }; 55 | System.out.println(getSmallSum(arr)); 56 | 57 | } 58 | 59 | } 60 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1014.md: -------------------------------------------------------------------------------- 1 | ## 自然数数组的排序 2 | 3 | **题目:** 4 | >给定一个长度为N的整数数组arr,其中有N个互不相等的自然数1~N,请实现arr的排序,但是不要把下标0~N-1位置上的数通过直接赋值的方式替换成1~N。 5 | 6 | ```java 7 | public class Problem_14_SortNaturalNumberArray { 8 | 9 | public static void sort1(int[] arr) { 10 | int tmp = 0; 11 | int next = 0; 12 | for (int i = 0; i != arr.length; i++) { 13 | tmp = arr[i]; 14 | while (arr[i] != i + 1) { 15 | next = arr[tmp - 1]; 16 | arr[tmp - 1] = tmp; 17 | tmp = next; 18 | } 19 | } 20 | } 21 | 22 | public static void sort2(int[] arr) { 23 | int tmp = 0; 24 | for (int i = 0; i != arr.length; i++) { 25 | while (arr[i] != i + 1) { 26 | tmp = arr[arr[i] - 1]; 27 | arr[arr[i] - 1] = arr[i]; 28 | arr[i] = tmp; 29 | } 30 | } 31 | } 32 | 33 | public static void printArray(int[] arr) { 34 | for (int i = 0; i != arr.length; i++) { 35 | System.out.print(arr[i] + " "); 36 | } 37 | System.out.println(); 38 | } 39 | 40 | public static void main(String[] args) { 41 | int[] arr = { 8, 2, 1, 6, 9, 3, 7, 5, 4 }; 42 | sort1(arr); 43 | printArray(arr); 44 | arr = new int[] { 8, 2, 1, 6, 9, 3, 7, 5, 4 }; 45 | sort2(arr); 46 | printArray(arr); 47 | 48 | } 49 | 50 | } 51 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1015.md: -------------------------------------------------------------------------------- 1 | ## 奇数下标都是奇数或者偶数下标都是偶数 2 | 3 | **题目:** 4 | >给定一个长度不小于2的数组arr,实现一个函数调整arr,要么让所有的偶数下标都是偶数,要么让所有的奇数下标都是奇数。 5 | 6 | ```java 7 | public class Problem_15_EvenInEvenOddInOdd { 8 | 9 | public static void modify(int[] arr) { 10 | if (arr == null || arr.length < 2) { 11 | return; 12 | } 13 | int even = 0; 14 | int odd = 1; 15 | int end = arr.length - 1; 16 | while (even <= end && odd <= end) { 17 | printArray(arr); 18 | if ((arr[end] & 1) == 0) { 19 | swap(arr, end, even); 20 | even += 2; 21 | } else { 22 | swap(arr, end, odd); 23 | odd += 2; 24 | } 25 | } 26 | } 27 | 28 | public static void swap(int[] arr, int index1, int index2) { 29 | int tmp = arr[index1]; 30 | arr[index1] = arr[index2]; 31 | arr[index2] = tmp; 32 | } 33 | 34 | public static void printArray(int[] arr) { 35 | for (int i = 0; i != arr.length; i++) { 36 | System.out.print(arr[i] + " "); 37 | } 38 | System.out.println(); 39 | } 40 | 41 | public static void main(String[] args) { 42 | int[] arr = { 1, 8, 3, 2, 4, 6 }; 43 | printArray(arr); 44 | modify(arr); 45 | printArray(arr); 46 | 47 | } 48 | 49 | } 50 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1016.md: -------------------------------------------------------------------------------- 1 | ## 子数组的最大累加和问题 2 | 3 | **题目:** 4 | >给定一个数组arr,返回子数组的最大累加和。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_16_SubArrayMaxSum { 10 | 11 | public static int maxSum(int[] arr) { 12 | if (arr == null || arr.length == 0) { 13 | return 0; 14 | } 15 | int max = Integer.MIN_VALUE; 16 | int cur = 0; 17 | for (int i = 0; i != arr.length; i++) { 18 | cur += arr[i]; 19 | max = Math.max(max, cur); 20 | cur = cur < 0 ? 0 : cur; 21 | } 22 | return max; 23 | } 24 | 25 | public static void printArray(int[] arr) { 26 | for (int i = 0; i != arr.length; i++) { 27 | System.out.print(arr[i] + " "); 28 | } 29 | System.out.println(); 30 | } 31 | 32 | public static void main(String[] args) { 33 | int[] arr1 = { -2, -3, -5, 40, -10, -10, 100, 1 }; 34 | System.out.println(maxSum(arr1)); 35 | 36 | int[] arr2 = { -2, -3, -5, 0, 1, 2, -1 }; 37 | System.out.println(maxSum(arr2)); 38 | 39 | int[] arr3 = { -2, -3, -5, -1 }; 40 | System.out.println(maxSum(arr3)); 41 | 42 | } 43 | 44 | } 45 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1017.md: -------------------------------------------------------------------------------- 1 | ## 子矩阵的最大累加和问题 2 | 3 | **题目:** 4 | >给定一个数组arr,返回子数组的最大累加和。 5 | 6 | ```java 7 | public class Problem_17_SubMatrixMaxSum { 8 | 9 | public static int maxSum(int[][] m) { 10 | if (m == null || m.length == 0 || m[0].length == 0) { 11 | return 0; 12 | } 13 | int max = Integer.MIN_VALUE; 14 | int cur = 0; 15 | int[] s = null; // 累加数组 16 | for (int i = 0; i != m.length; i++) { 17 | s = new int[m[0].length]; 18 | for (int j = i; j != m.length; j++) { 19 | cur = 0; 20 | for (int k = 0; k != s.length; k++) { 21 | s[k] += m[j][k]; 22 | cur += s[k]; 23 | max = Math.max(max, cur); 24 | cur = cur < 0 ? 0 : cur; 25 | } 26 | } 27 | } 28 | return max; 29 | } 30 | 31 | public static void main(String[] args) { 32 | int[][] matrix = { { -90, 48, 78 }, { 64, -40, 64 }, { -81, -7, 66 } }; 33 | System.out.println(maxSum(matrix)); 34 | 35 | } 36 | 37 | } 38 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1018.md: -------------------------------------------------------------------------------- 1 | ## 在数组中找到一个局部最小的位置 2 | 3 | **题目:** 4 | >给定无序数组arr,已知arr中任意两个相邻的数都不相等,写一个函数,只需返回arr中任意一个局部最小出现的位置即可。 5 | 6 | 7 | ```java 8 | public class Problem_18_FindOneLessValueIndex { 9 | 10 | public static int getLessIndex(int[] arr) { 11 | if (arr == null || arr.length == 0) { 12 | return -1; // no exist 13 | } 14 | if (arr.length == 1 || arr[0] < arr[1]) { 15 | return 0; 16 | } 17 | if (arr[arr.length - 1] < arr[arr.length - 2]) { 18 | return arr.length - 1; 19 | } 20 | int left = 1; 21 | int right = arr.length - 2; 22 | int mid = 0; 23 | while (left < right) { 24 | mid = (left + right) / 2; 25 | if (arr[mid] > arr[mid - 1]) { 26 | right = mid - 1; 27 | } else if (arr[mid] > arr[mid + 1]) { 28 | left = mid + 1; 29 | } else { 30 | return mid; 31 | } 32 | } 33 | return left; 34 | } 35 | 36 | public static void printArray(int[] arr) { 37 | for (int i = 0; i != arr.length; i++) { 38 | System.out.print(arr[i] + " "); 39 | } 40 | System.out.println(); 41 | } 42 | 43 | public static void main(String[] args) { 44 | int[] arr = { 6, 5, 3, 4, 6, 7, 8 }; 45 | printArray(arr); 46 | int index = getLessIndex(arr); 47 | System.out.println("index: " + index + ", value: " + arr[index]); 48 | 49 | } 50 | 51 | } 52 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1019.md: -------------------------------------------------------------------------------- 1 | ## 数组中子数组的最大累乘积 2 | 3 | **题目:** 4 | >给定一个double类型的数组arr,其中的元素可正、可负、可0,返回子数组累乘的最大乘积。 5 | 6 | ```java 7 | public class Problem_19_SubArrayMaxProduct { 8 | 9 | public static double maxProduct(double[] arr) { 10 | if (arr == null || arr.length == 0) { 11 | return 0; 12 | } 13 | double max = arr[0]; 14 | double min = arr[0]; 15 | double res = arr[0]; 16 | double maxEnd = 0; 17 | double minEnd = 0; 18 | for (int i = 1; i < arr.length; ++i) { 19 | maxEnd = max * arr[i]; 20 | minEnd = min * arr[i]; 21 | max = Math.max(Math.max(maxEnd, minEnd), arr[i]); 22 | min = Math.min(Math.min(maxEnd, minEnd), arr[i]); 23 | res = Math.max(res, max); 24 | } 25 | return res; 26 | } 27 | 28 | public static void main(String[] args) { 29 | double[] arr = { -2.5, 4, 0, 3, 0.5, 8, -1 }; 30 | System.out.println(maxProduct(arr)); 31 | 32 | } 33 | 34 | } 35 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1022.md: -------------------------------------------------------------------------------- 1 | ## 不包含本位置值的累乘数组 2 | 3 | **题目:** 4 | >给定一个整型数组arr,返回不包含本位置值的累乘数组。 5 | 6 | 7 | ```java 8 | public class Problem_22_MultiplyExceptOwn { 9 | 10 | public static int[] product1(int[] arr) { 11 | if (arr == null || arr.length < 2) { 12 | return null; 13 | } 14 | int count = 0; 15 | int all = 1; 16 | for (int i = 0; i != arr.length; i++) { 17 | if (arr[i] != 0) { 18 | all *= arr[i]; 19 | } else { 20 | count++; 21 | } 22 | } 23 | int[] res = new int[arr.length]; 24 | if (count == 0) { 25 | for (int i = 0; i != arr.length; i++) { 26 | res[i] = all / arr[i]; 27 | } 28 | } 29 | if (count == 1) { 30 | for (int i = 0; i != arr.length; i++) { 31 | if (arr[i] == 0) { 32 | res[i] = all; 33 | } 34 | } 35 | } 36 | return res; 37 | } 38 | 39 | public static int[] product2(int[] arr) { 40 | if (arr == null || arr.length < 2) { 41 | return null; 42 | } 43 | int[] res = new int[arr.length]; 44 | res[0] = arr[0]; 45 | for (int i = 1; i < arr.length; i++) { 46 | res[i] = res[i - 1] * arr[i]; 47 | } 48 | int tmp = 1; 49 | for (int i = arr.length - 1; i > 0; i--) { 50 | res[i] = res[i - 1] * tmp; 51 | tmp *= arr[i]; 52 | } 53 | res[0] = tmp; 54 | return res; 55 | } 56 | 57 | public static void printArray(int[] arr) { 58 | for (int i = 0; i != arr.length; i++) { 59 | System.out.print(arr[i] + " "); 60 | } 61 | System.out.println(); 62 | } 63 | 64 | public static void main(String[] args) { 65 | int[] arr = { 1, 2, 3, 4 }; 66 | int[] res1 = product1(arr); 67 | printArray(res1); 68 | int[] res2 = product2(arr); 69 | printArray(res2); 70 | 71 | } 72 | } 73 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1023.md: -------------------------------------------------------------------------------- 1 | ## 数组的partition调整 2 | 3 | **题目:** 4 | >给定一个有序数组arr,调整arr使得这个数组的左半部分没有重复元素且升序,而不用保证右部分是否有序。 5 | 6 | ```java 7 | public class Problem_23_PartitionArray { 8 | 9 | public static void leftUnique(int[] arr) { 10 | if (arr == null || arr.length < 2) { 11 | return; 12 | } 13 | int u = 0; 14 | int i = 1; 15 | while (i != arr.length) { 16 | if (arr[i++] != arr[u]) { 17 | swap(arr, ++u, i - 1); 18 | } 19 | } 20 | } 21 | 22 | public static void sort(int[] arr) { 23 | if (arr == null || arr.length < 2) { 24 | return; 25 | } 26 | int left = -1; 27 | int index = 0; 28 | int right = arr.length; 29 | while (index < right) { 30 | if (arr[index] == 0) { 31 | swap(arr, ++left, index++); 32 | } else if (arr[index] == 2) { 33 | swap(arr, index, --right); 34 | } else { 35 | index++; 36 | } 37 | } 38 | } 39 | 40 | public static void swap(int[] arr, int index1, int index2) { 41 | int tmp = arr[index1]; 42 | arr[index1] = arr[index2]; 43 | arr[index2] = tmp; 44 | } 45 | 46 | public static void printArray(int[] arr) { 47 | for (int i = 0; i != arr.length; i++) { 48 | System.out.print(arr[i] + " "); 49 | } 50 | System.out.println(); 51 | } 52 | 53 | public static void main(String[] args) { 54 | int[] arr1 = { 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9 }; 55 | printArray(arr1); 56 | leftUnique(arr1); 57 | printArray(arr1); 58 | 59 | System.out.println(); 60 | 61 | int[] arr2 = { 2, 1, 2, 0, 1, 1, 2, 2, 0 }; 62 | printArray(arr2); 63 | sort(arr2); 64 | printArray(arr2); 65 | 66 | } 67 | 68 | } 69 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1024.md: -------------------------------------------------------------------------------- 1 | ## 求最短通路值 2 | 3 | **题目:** 4 | >用一个整型矩阵matrix表示一个网络,1代表有路,0代表无路,每一个位置只要不越界,都有上下左右4个方向,求从最左上角到最右下角的最短通路值。 5 | 6 | ```java 7 | import java.util.LinkedList; 8 | import java.util.Queue; 9 | 10 | public class Problem_24_MinPathValue { 11 | 12 | public static int minPathValue(int[][] m) { 13 | if (m == null || m.length == 0 || m[0].length == 0 || m[0][0] != 1 14 | || m[m.length - 1][m[0].length - 1] != 1) { 15 | return 0; 16 | } 17 | int res = 0; 18 | int[][] map = new int[m.length][m[0].length]; 19 | map[0][0] = 1; 20 | Queue rQ = new LinkedList(); 21 | Queue cQ = new LinkedList(); 22 | rQ.add(0); 23 | cQ.add(0); 24 | int r = 0; 25 | int c = 0; 26 | while (!rQ.isEmpty()) { 27 | r = rQ.poll(); 28 | c = cQ.poll(); 29 | if (r == m.length - 1 && c == m[0].length - 1) { 30 | return map[r][c]; 31 | } 32 | walkTo(map[r][c], r - 1, c, m, map, rQ, cQ); // up 33 | walkTo(map[r][c], r + 1, c, m, map, rQ, cQ); // down 34 | walkTo(map[r][c], r, c - 1, m, map, rQ, cQ); // left 35 | walkTo(map[r][c], r, c + 1, m, map, rQ, cQ); // right 36 | } 37 | return res; 38 | } 39 | 40 | public static void walkTo(int pre, int toR, int toC, int[][] m, 41 | int[][] map, Queue rQ, Queue cQ) { 42 | if (toR < 0 || toR == m.length || toC < 0 || toC == m[0].length 43 | || m[toR][toC] != 1 || map[toR][toC] != 0) { 44 | return; 45 | } 46 | map[toR][toC] = pre + 1; 47 | rQ.add(toR); 48 | cQ.add(toC); 49 | } 50 | 51 | public static void main(String[] args) { 52 | int[][] matrix = { { 1, 0, 1, 1, 1, 0, 1, 1, 1 }, 53 | { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, 54 | { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, 55 | { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, 56 | { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, { 1, 1, 1, 0, 1, 1, 1, 0, 1 } }; 57 | System.out.println(minPathValue(matrix)); 58 | 59 | } 60 | } 61 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1025.md: -------------------------------------------------------------------------------- 1 | ## 数组中未出现的最小正整数 2 | 3 | **题目:** 4 | >给定一个无序整型数组arr,找到数组中未出现的最小正整数。 5 | 6 | 7 | ```java 8 | public class Problem_25_SmallestMissNum { 9 | 10 | public static int missNum(int[] arr) { 11 | int l = 0; 12 | int r = arr.length; 13 | while (l < r) { 14 | if (arr[l] == l + 1) { 15 | l++; 16 | } else if (arr[l] <= l || arr[l] > r || arr[arr[l] - 1] == arr[l]) { 17 | arr[l] = arr[--r]; 18 | } else { 19 | swap(arr, l, arr[l] - 1); 20 | } 21 | } 22 | return l + 1; 23 | } 24 | 25 | public static void swap(int[] arr, int index1, int index2) { 26 | int tmp = arr[index1]; 27 | arr[index1] = arr[index2]; 28 | arr[index2] = tmp; 29 | } 30 | 31 | public static void main(String[] args) { 32 | int[] arr = { -1, 0, 2, 1, 3, 5 }; 33 | System.out.println(missNum(arr)); 34 | 35 | } 36 | } 37 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter07_ArrayAndMatrix/Q1026.md: -------------------------------------------------------------------------------- 1 | ## 数组排序之后相邻数的最大差值 2 | 3 | **题目:** 4 | >给定一个整型数组arr,返回排序后的相邻两数的最大差值。 5 | 6 | ```java 7 | public class Problem_26_MaxGap { 8 | 9 | public static int maxGap(int[] nums) { 10 | if (nums == null || nums.length < 2) { 11 | return 0; 12 | } 13 | int len = nums.length; 14 | int min = Integer.MAX_VALUE; 15 | int max = Integer.MIN_VALUE; 16 | for (int i = 0; i < len; i++) { 17 | min = Math.min(min, nums[i]); 18 | max = Math.max(max, nums[i]); 19 | } 20 | if (min == max) { 21 | return 0; 22 | } 23 | boolean[] hasNum = new boolean[len + 1]; 24 | int[] maxs = new int[len + 1]; 25 | int[] mins = new int[len + 1]; 26 | int bid = 0; 27 | for (int i = 0; i < len; i++) { 28 | bid = bucket(nums[i], len, min, max); 29 | mins[bid] = hasNum[bid] ? Math.min(mins[bid], nums[i]) : nums[i]; 30 | maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], nums[i]) : nums[i]; 31 | hasNum[bid] = true; 32 | } 33 | int res = 0; 34 | int lastMax = maxs[0]; 35 | int i = 1; 36 | for (; i <= len; i++) { 37 | if (hasNum[i]) { 38 | res = Math.max(res, mins[i] - lastMax); 39 | lastMax = maxs[i]; 40 | } 41 | } 42 | return res; 43 | } 44 | 45 | public static int bucket(long num, long len, long min, long max) { 46 | return (int) ((num - min) * len / (max - min)); 47 | } 48 | 49 | public static void main(String[] args) { 50 | int[] arr = { 11, 10, 9, 3, 1, 12 }; 51 | System.out.println(maxGap(arr)); 52 | 53 | } 54 | 55 | } 56 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1002.md: -------------------------------------------------------------------------------- 1 | ## 一行代码求两个数的最大公约数 2 | 3 | **题目:** 4 | >给定两个不等于0的整数M和N,求M和N的最大公约数。 5 | 6 | 7 | ```java 8 | public class Problem_02_GCD { 9 | 10 | public static int gcd(int m, int n) { 11 | return n == 0 ? m : gcd(n, m % n); 12 | } 13 | 14 | public static void main(String[] args) { 15 | 16 | System.out.println(gcd(18, 27)); 17 | 18 | } 19 | 20 | } 21 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1003.md: -------------------------------------------------------------------------------- 1 | ## 有关阶乘的两个问题 2 | 3 | **题目:** 4 | >给定一个非负整数N,返回N!结果的末尾为0的数量。 5 | 6 | ```java 7 | public class Problem_03_FactorialProblem { 8 | 9 | public static int zeroNum1(int num) { 10 | if (num < 0) { 11 | return 0; 12 | } 13 | int res = 0; 14 | int cur = 0; 15 | for (int i = 5; i < num + 1; i = i + 5) { 16 | cur = i; 17 | while (cur % 5 == 0) { 18 | res++; 19 | cur /= 5; 20 | } 21 | } 22 | return res; 23 | } 24 | 25 | public static int zeroNum2(int num) { 26 | if (num < 0) { 27 | return 0; 28 | } 29 | int res = 0; 30 | while (num != 0) { 31 | res += num / 5; 32 | num /= 5; 33 | } 34 | return res; 35 | } 36 | 37 | public static int rightOne1(int num) { 38 | if (num < 1) { 39 | return -1; 40 | } 41 | int res = 0; 42 | while (num != 0) { 43 | num >>>= 1; 44 | res += num; 45 | } 46 | return res; 47 | } 48 | 49 | public static int rightOne2(int num) { 50 | if (num < 1) { 51 | return -1; 52 | } 53 | int ones = 0; 54 | int tmp = num; 55 | while (tmp != 0) { 56 | ones += (tmp & 1) != 0 ? 1 : 0; 57 | tmp >>>= 1; 58 | } 59 | return num - ones; 60 | } 61 | 62 | public static void main(String[] args) { 63 | int num = 1000000000; 64 | 65 | System.out.println(zeroNum2(num)); 66 | System.out.println(zeroNum1(num)); 67 | 68 | System.out.println(rightOne2(num)); 69 | System.out.println(rightOne1(num)); 70 | 71 | } 72 | 73 | } 74 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1004.md: -------------------------------------------------------------------------------- 1 | ## 判断一个点是否在矩形内部 2 | 3 | **题目:** 4 | >在二维坐标系中,所有的值都是double类型那么一个矩形可以由4个点来代表(x1,y1)为最左的点、(x2,y2)为最上的点、(x3,y3)为最下的点、(x4,y4)为最右的点。给定4个点代表的矩形,再给定一个点(x,y),判断(x,y)是否在矩形中。 5 | 6 | 7 | 8 | 9 | ```java 10 | public class Problem_04_PointInRectangle { 11 | 12 | public static boolean isInside(double x1, double y1, double x4, double y4, 13 | double x, double y) { 14 | if (x <= x1) { 15 | return false; 16 | } 17 | if (x >= x4) { 18 | return false; 19 | } 20 | if (y >= y1) { 21 | return false; 22 | } 23 | if (y <= y4) { 24 | return false; 25 | } 26 | return true; 27 | } 28 | 29 | public static boolean isInside(double x1, double y1, double x2, double y2, 30 | double x3, double y3, double x4, double y4, double x, double y) { 31 | if (y1 == y2) { 32 | return isInside(x1, y1, x4, y4, x, y); 33 | } 34 | double l = Math.abs(y4 - y3); 35 | double k = Math.abs(x4 - x3); 36 | double s = Math.sqrt(k * k + l * l); 37 | double sin = l / s; 38 | double cos = k / s; 39 | double x1R = cos * x1 + sin * y1; 40 | double y1R = -x1 * sin + y1 * cos; 41 | double x4R = cos * x4 + sin * y4; 42 | double y4R = -x4 * sin + y4 * cos; 43 | double xR = cos * x + sin * y; 44 | double yR = -x * sin + y * cos; 45 | return isInside(x1R, y1R, x4R, y4R, xR, yR); 46 | } 47 | 48 | public static void main(String[] args) { 49 | // (x1,y1),(x2,y2),(x3,y3),(x4,y4) stand for a Rectangle. 50 | double x1 = 0; 51 | double y1 = 3;// (x1,y1) should be the most left 52 | double x2 = 3; 53 | double y2 = 7;// (x2,y2) should be the most top. 54 | double x3 = 4; 55 | double y3 = 0;// (x3,y3) should be the most below. 56 | double x4 = 7; 57 | double y4 = 4;// (x4,y4) should be the most right. 58 | 59 | double x = 4; 60 | double y = 3; 61 | System.out.print(isInside(x1, y1, x2, y2, x3, y3, x4, y4, x, y)); 62 | 63 | } 64 | 65 | } 66 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1006.md: -------------------------------------------------------------------------------- 1 | ## 折纸问题 2 | 3 | **题目:** 4 | >请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折l次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。给定一个输入参数N,代表纸条都从下边向上边连续对折N次,请从上到下打印所有折痕的方向。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_06_PaperFolding { 10 | 11 | public static void printAllFolds(int N) { 12 | printProcess(1, N, true); 13 | } 14 | 15 | public static void printProcess(int i, int N, boolean down) { 16 | if (i > N) { 17 | return; 18 | } 19 | printProcess(i + 1, N, true); 20 | System.out.println(down ? "down " : "up "); 21 | printProcess(i + 1, N, false); 22 | } 23 | 24 | public static void main(String[] args) { 25 | int N = 4; 26 | printAllFolds(N); 27 | 28 | } 29 | } 30 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1007.md: -------------------------------------------------------------------------------- 1 | ## 蓄水池算法 2 | 3 | **题目:** 4 | >有一个机器按自然数序列的方式吐出球(1号球,2号球,3号球,......),你有一个袋子,袋子最多只能装下K个球,并且出袋子以外,你没有更多的空间。设计一种选择方式,使得当机器吐出第N号球的时候(N>K),你袋子中的球数是K个,同时可以保证从1号球到N号球中的每一个,被选进袋子的概率为K/N。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_07_ReservoirSampling { 10 | 11 | // 一个简单的随机函数,决定一个事情做还是不做 12 | public static int rand(int max) { 13 | return (int) (Math.random() * max) + 1; 14 | } 15 | 16 | public static int[] getKNumsRand(int k, int max) { 17 | if (max < 1 || k < 1) { 18 | return null; 19 | } 20 | int[] res = new int[Math.min(k, max)]; 21 | for (int i = 0; i != res.length; i++) { 22 | res[i] = i + 1; // 前k个数直接进袋子 23 | } 24 | for (int i = k + 1; i < max + 1; i++) { 25 | if (rand(i) <= k) { // 决定i进不进袋子 26 | res[rand(k) - 1] = i; // i随机替掉袋子中的一个 27 | } 28 | } 29 | return res; 30 | } 31 | 32 | public static void printArray(int[] arr) { 33 | for (int i = 0; i != arr.length; i++) { 34 | System.out.print(arr[i] + " "); 35 | } 36 | System.out.println(); 37 | } 38 | 39 | public static void main(String[] args) { 40 | int[] res = getKNumsRand(10, 10000); 41 | printArray(res); 42 | } 43 | 44 | } 45 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1009.md: -------------------------------------------------------------------------------- 1 | ## 最大的leftMax与rightMax之差的绝对值 2 | 3 | **题目:** 4 | >给定一个长度为 N(N>1)的整型数组arr,可以划分成左右两个部分,左部分为arr[0..K],右部分为arr[K+1..N-1],K可以取值的范围是[0,N-2]。求这么多划分方案中,左部分中的最大值减去右部分最大值的绝对值中,最大是多少? 5 | 6 | ```java 7 | public class Problem_09_MaxABSBetweenLeftAndRight { 8 | 9 | public static int maxABS1(int[] arr) { 10 | int res = Integer.MIN_VALUE; 11 | int maxLeft = 0; 12 | int maxRight = 0; 13 | for (int i = 0; i != arr.length - 1; i++) { 14 | maxLeft = Integer.MIN_VALUE; 15 | for (int j = 0; j != i + 1; j++) { 16 | maxLeft = Math.max(arr[j], maxLeft); 17 | } 18 | maxRight = Integer.MIN_VALUE; 19 | for (int j = i + 1; j != arr.length; j++) { 20 | maxRight = Math.max(arr[j], maxRight); 21 | } 22 | res = Math.max(Math.abs(maxLeft - maxRight), res); 23 | } 24 | return res; 25 | } 26 | 27 | public static int maxABS2(int[] arr) { 28 | int[] lArr = new int[arr.length]; 29 | int[] rArr = new int[arr.length]; 30 | lArr[0] = arr[0]; 31 | rArr[arr.length - 1] = arr[arr.length - 1]; 32 | for (int i = 1; i < arr.length; i++) { 33 | lArr[i] = Math.max(lArr[i - 1], arr[i]); 34 | } 35 | for (int i = arr.length - 2; i > -1; i--) { 36 | rArr[i] = Math.max(rArr[i + 1], arr[i]); 37 | } 38 | int max = 0; 39 | for (int i = 0; i < arr.length - 1; i++) { 40 | max = Math.max(max, Math.abs(lArr[i] - rArr[i + 1])); 41 | } 42 | return max; 43 | } 44 | 45 | public static int maxABS3(int[] arr) { 46 | int max = Integer.MIN_VALUE; 47 | for (int i = 0; i < arr.length; i++) { 48 | max = Math.max(arr[i], max); 49 | } 50 | return max - Math.min(arr[0], arr[arr.length - 1]); 51 | } 52 | 53 | public static int[] generateRandomArray(int length) { 54 | int[] arr = new int[length]; 55 | for (int i = 0; i != arr.length; i++) { 56 | arr[i] = (int) (Math.random() * 1000) - 499; 57 | } 58 | return arr; 59 | } 60 | 61 | public static void main(String[] args) { 62 | int[] arr = generateRandomArray(200); 63 | System.out.println(maxABS1(arr)); 64 | System.out.println(maxABS2(arr)); 65 | System.out.println(maxABS3(arr)); 66 | } 67 | } 68 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1011.md: -------------------------------------------------------------------------------- 1 | ## 设计RandomPool结构 2 | 3 | **题目:** 4 | >设计一种结构,在该结构中有如下三个功能: 5 | - insert(key):将某个key加入到该结构,做到不重复加入 6 | - delete(key):将原本在结构中的某个key移除 7 | - getRandom() :等概率随机返回结构中的任何一个key 8 | 9 | 10 | ```java 11 | import java.util.HashMap; 12 | 13 | public class Problem_11_RandomPool { 14 | 15 | public static class Pool { 16 | private HashMap keyIndexMap; 17 | private HashMap indexKeyMap; 18 | private int size; 19 | 20 | public Pool() { 21 | this.keyIndexMap = new HashMap(); 22 | this.indexKeyMap = new HashMap(); 23 | this.size = 0; 24 | } 25 | 26 | public void insert(K key) { 27 | if (!this.keyIndexMap.containsKey(key)) { 28 | this.keyIndexMap.put(key, this.size); 29 | this.indexKeyMap.put(this.size++, key); 30 | } 31 | } 32 | 33 | public void delete(K key) { 34 | if (this.keyIndexMap.containsKey(key)) { 35 | int deleteIndex = this.keyIndexMap.get(key); 36 | int lastIndex = --this.size; 37 | K lastKey = this.indexKeyMap.get(lastIndex); 38 | this.keyIndexMap.put(lastKey, deleteIndex); 39 | this.indexKeyMap.put(deleteIndex, lastKey); 40 | this.keyIndexMap.remove(key); 41 | this.indexKeyMap.remove(lastIndex); 42 | } 43 | } 44 | 45 | public K getRandom() { 46 | if (this.size == 0) { 47 | return null; 48 | } 49 | int randomIndex = (int) (Math.random() * this.size); 50 | return this.indexKeyMap.get(randomIndex); 51 | } 52 | 53 | } 54 | 55 | public static void main(String[] args) { 56 | Pool pool = new Pool(); 57 | pool.insert("zuo"); 58 | pool.insert("cheng"); 59 | pool.insert("yun"); 60 | System.out.println(pool.getRandom()); 61 | System.out.println(pool.getRandom()); 62 | System.out.println(pool.getRandom()); 63 | System.out.println(pool.getRandom()); 64 | System.out.println(pool.getRandom()); 65 | System.out.println(pool.getRandom()); 66 | 67 | } 68 | 69 | } 70 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1012.md: -------------------------------------------------------------------------------- 1 | ## 调整[0,x)区间上的数出现的概率 2 | 3 | **题目:** 4 | >假设函数Math.random()等概率随机返回一个在[0,1)范围上的数,那么我们知道,在[0,x)区间上的数出现的概率为x(O distancesArray 12 | pathsToDistans(paths); 13 | 14 | // distancesArray -> numArray 15 | distansToNums(paths); 16 | } 17 | 18 | public static void pathsToDistans(int[] paths) { 19 | int cap = 0; 20 | for (int i = 0; i != paths.length; i++) { 21 | if (paths[i] == i) { 22 | cap = i; 23 | } else if (paths[i] > -1) { 24 | int curI = paths[i]; 25 | paths[i] = -1; 26 | int preI = i; 27 | while (paths[curI] != curI) { 28 | if (paths[curI] > -1) { 29 | int nextI = paths[curI]; 30 | paths[curI] = preI; 31 | preI = curI; 32 | curI = nextI; 33 | } else { 34 | break; 35 | } 36 | } 37 | int value = paths[curI] == curI ? 0 : paths[curI]; 38 | while (paths[preI] != -1) { 39 | int lastPreI = paths[preI]; 40 | paths[preI] = --value; 41 | curI = preI; 42 | preI = lastPreI; 43 | } 44 | paths[preI] = --value; 45 | } 46 | } 47 | paths[cap] = 0; 48 | } 49 | 50 | public static void distansToNums(int[] disArr) { 51 | for (int i = 0; i != disArr.length; i++) { 52 | int index = disArr[i]; 53 | if (index < 0) { 54 | disArr[i] = 0; // important 55 | while (true) { 56 | index = -index; 57 | if (disArr[index] > -1) { 58 | disArr[index]++; 59 | break; 60 | } else { 61 | int nextIndex = disArr[index]; 62 | disArr[index] = 1; 63 | index = nextIndex; 64 | } 65 | } 66 | } 67 | } 68 | disArr[0] = 1; 69 | } 70 | 71 | public static void printArray(int[] arr) { 72 | if (arr == null || arr.length == 0) { 73 | return; 74 | } 75 | for (int i = 0; i != arr.length; i++) { 76 | System.out.print(arr[i] + " "); 77 | } 78 | System.out.println(); 79 | } 80 | 81 | public static void main(String[] args) { 82 | int[] paths = { 9, 1, 4, 9, 0, 4, 8, 9, 0, 1 }; 83 | printArray(paths); 84 | pathsToNums(paths); 85 | printArray(paths); 86 | 87 | } 88 | 89 | } 90 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1016.md: -------------------------------------------------------------------------------- 1 | ## 1到n中1出现的次数 2 | 3 | **题目:** 4 | >给定一个整数n,返回从1到n的数字中1出现的个数。 5 | 6 | 7 | 8 | ```java 9 | public class Problem_16_OneNumber { 10 | 11 | public static int solution1(int num) { 12 | if (num < 1) { 13 | return 0; 14 | } 15 | int count = 0; 16 | for (int i = 1; i != num + 1; i++) { 17 | count += get1Nums(i); 18 | } 19 | return count; 20 | } 21 | 22 | public static int get1Nums(int num) { 23 | int res = 0; 24 | while (num != 0) { 25 | if (num % 10 == 1) { 26 | res++; 27 | } 28 | num /= 10; 29 | } 30 | return res; 31 | } 32 | 33 | public static int solution2(int num) { 34 | if (num < 1) { 35 | return 0; 36 | } 37 | int len = getLenOfNum(num); 38 | if (len == 1) { 39 | return 1; 40 | } 41 | int tmp1 = powerBaseOf10(len - 1); 42 | int first = num / tmp1; 43 | int firstOneNum = first == 1 ? num % tmp1 + 1 : tmp1; 44 | int otherOneNum = first * (len - 1) * (tmp1 / 10); 45 | return firstOneNum + otherOneNum + solution2(num % tmp1); 46 | } 47 | 48 | public static int getLenOfNum(int num) { 49 | int len = 0; 50 | while (num != 0) { 51 | len++; 52 | num /= 10; 53 | } 54 | return len; 55 | } 56 | 57 | public static int powerBaseOf10(int base) { 58 | return (int) Math.pow(10, base); 59 | } 60 | 61 | public static void main(String[] args) { 62 | int num = 50000000; 63 | long start1 = System.currentTimeMillis(); 64 | System.out.println(solution1(num)); 65 | long end1 = System.currentTimeMillis(); 66 | System.out.println("cost time: " + (end1 - start1) + " ms"); 67 | 68 | long start2 = System.currentTimeMillis(); 69 | System.out.println(solution2(num)); 70 | long end2 = System.currentTimeMillis(); 71 | System.out.println("cost time: " + (end2 - start2) + " ms"); 72 | 73 | } 74 | } 75 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1017.md: -------------------------------------------------------------------------------- 1 | ## 从N个数中等概率打印M个数 2 | 3 | **题目:** 4 | >给定一个长度为N且没有重复元素的数组arr和一个整数n,实现函数等概率随机打印arr中的M个数。 5 | 6 | ```java 7 | public class Problem_17_PrintRandomM { 8 | 9 | public static void printRandM(int[] arr, int m) { 10 | if (arr == null || arr.length == 0 || m < 0) { 11 | return; 12 | } 13 | m = Math.min(arr.length, m); 14 | int count = 0; 15 | int i = 0; 16 | while (count < m) { 17 | i = (int) (Math.random() * (arr.length - count)); 18 | System.out.println(arr[i]); 19 | swap(arr, arr.length - count++ - 1, i); 20 | } 21 | } 22 | 23 | public static void swap(int[] arr, int index1, int index2) { 24 | int tmp = arr[index1]; 25 | arr[index1] = arr[index2]; 26 | arr[index2] = tmp; 27 | } 28 | 29 | public static void main(String[] args) { 30 | int[] arr = { 6, 2, 3, 5, 1, 4 }; 31 | int m = 1; 32 | printRandM(arr, m); 33 | 34 | } 35 | 36 | } 37 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1018.md: -------------------------------------------------------------------------------- 1 | ## 判读一个数是否是回文数 2 | 3 | **题目:** 4 | >定义回文数的概念如下: 5 | - 如果一个非负数左右完全对应,则概述是回文数,例如:121,22等 6 | - 如果一个负数的绝对值左右完全对应,也是回文数,例如:-21,-22等 7 | 给定一个32位整数num,判断num是否是回文数。 8 | 9 | 10 | ```java 11 | public class Problem_18_PalindromeNumber { 12 | 13 | public static boolean isPalindrome(int n) { 14 | if (n == Integer.MIN_VALUE) { 15 | return false; 16 | } 17 | n = Math.abs(n); 18 | int help = 1; 19 | while (n / help >= 10) { // 防止help溢出 20 | help *= 10; 21 | } 22 | while (n != 0) { 23 | if (n / help != n % 10) { 24 | return false; 25 | } 26 | n = (n % help) / 10; 27 | help /= 100; 28 | } 29 | return true; 30 | } 31 | 32 | public static void main(String[] args) { 33 | int test = -10001; 34 | System.out.println(isPalindrome(test)); 35 | 36 | } 37 | 38 | } 39 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1019.md: -------------------------------------------------------------------------------- 1 | ## 在有序旋转数组中找到最小值 2 | 3 | **题目:** 4 | >有序数组arr可能经过一次旋转处理,也可能没有,且arr可能存在重复的数。例如,有序数组[1,2,3,4,5,6,7],可以旋转处理成[4,5,6,7,1,2,3]等。给定一个可能旋转过的有序数组arr,返回arr中的最小值。 5 | 6 | ```java 7 | public class Problem_19_SortedRatateArrayFindMin { 8 | 9 | public static int getMin(int[] arr) { 10 | int low = 0; 11 | int high = arr.length - 1; 12 | int mid = 0; 13 | while (low < high) { 14 | if (low == high - 1) { 15 | break; 16 | } 17 | if (arr[low] < arr[high]) { 18 | return arr[low]; 19 | } 20 | mid = (low + high) / 2; 21 | if (arr[low] > arr[mid]) { 22 | high = mid; 23 | continue; 24 | } 25 | if (arr[mid] > arr[high]) { 26 | low = mid; 27 | continue; 28 | } 29 | while (low < mid) { 30 | if (arr[low] == arr[mid]) { 31 | low++; 32 | } else if (arr[low] < arr[mid]) { 33 | return arr[low]; 34 | } else { 35 | high = mid; 36 | break; 37 | } 38 | } 39 | } 40 | return Math.min(arr[low], arr[high]); 41 | } 42 | 43 | public static void main(String[] args) { 44 | int[] test = { 4, 5, 5, 5, 1, 2, 3 }; 45 | System.out.println(getMin(test)); 46 | 47 | } 48 | 49 | } 50 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1020.md: -------------------------------------------------------------------------------- 1 | ## 在有序旋转数组中找到一个数 2 | 3 | **题目:** 4 | >有序数组arr可能经过一次旋转处理,也可能没有,且arr可能存在重复的数。例如,有序数组[1,2,3,4,5,6,7],可以旋转处理成[4,5,6,7,l,2,3]等。给定一个可能旋转过的有序数组arr,再给定一个数num,返回arr中是否含有num。 5 | 6 | 7 | ```java 8 | public class Problem_20_SortedRatateArrayFindNum { 9 | 10 | public static boolean isContains(int[] arr, int num) { 11 | int low = 0; 12 | int high = arr.length - 1; 13 | int mid = 0; 14 | while (low <= high) { 15 | mid = (low + high) / 2; 16 | if (arr[mid] == num) { 17 | return true; 18 | } 19 | if (arr[low] == arr[mid] && arr[mid] == arr[high]) { 20 | while (low != mid && arr[low] == arr[mid]) { 21 | low++; 22 | } 23 | if (low == mid) { 24 | low = mid + 1; 25 | continue; 26 | } 27 | } 28 | if (arr[low] != arr[mid]) { 29 | if (arr[mid] > arr[low]) { 30 | if (num >= arr[low] && num < arr[mid]) { 31 | high = mid - 1; 32 | } else { 33 | low = mid + 1; 34 | } 35 | } else { 36 | if (num > arr[mid] && num <= arr[high]) { 37 | low = mid + 1; 38 | } else { 39 | high = mid - 1; 40 | } 41 | } 42 | } else { 43 | if (arr[mid] < arr[high]) { 44 | if (num > arr[mid] && num <= arr[high]) { 45 | low = mid + 1; 46 | } else { 47 | high = mid - 1; 48 | } 49 | } else { 50 | if (num >= arr[low] && num < arr[mid]) { 51 | high = mid - 1; 52 | } else { 53 | low = mid + 1; 54 | } 55 | } 56 | } 57 | } 58 | return false; 59 | } 60 | 61 | public static void main(String[] args) { 62 | int[] arr = { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5 }; 63 | int num = 10; 64 | System.out.println(isContains(arr, num)); 65 | 66 | } 67 | } 68 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1023.md: -------------------------------------------------------------------------------- 1 | ## 一种消息接收并打印的结构设计 2 | 3 | 4 | ```java 5 | import java.util.HashMap; 6 | 7 | public class Problem_23_ReceiveAndPrintOrderLine { 8 | 9 | // 简单的单链表节点结构 10 | public static class Node { 11 | public int num; 12 | public Node next; 13 | 14 | public Node(int num) { 15 | this.num = num; 16 | } 17 | } 18 | 19 | public static class MessageBox { 20 | private HashMap headMap; 21 | private HashMap tailMap; 22 | private int lastPrint; 23 | 24 | public MessageBox() { 25 | headMap = new HashMap(); 26 | tailMap = new HashMap(); 27 | lastPrint = 0; 28 | } 29 | 30 | public void receive(int num) { 31 | if (num < 1) { 32 | return; 33 | } 34 | Node cur = new Node(num); 35 | headMap.put(num, cur); 36 | tailMap.put(num, cur); 37 | if (tailMap.containsKey(num - 1)) { 38 | tailMap.get(num - 1).next = cur; 39 | tailMap.remove(num - 1); 40 | headMap.remove(num); 41 | } 42 | if (headMap.containsKey(num + 1)) { 43 | cur.next = headMap.get(num + 1); 44 | tailMap.remove(num); 45 | headMap.remove(num + 1); 46 | } 47 | if (headMap.containsKey(lastPrint + 1)) { 48 | print(); 49 | } 50 | } 51 | 52 | private void print() { 53 | Node node = headMap.get(++lastPrint); 54 | headMap.remove(lastPrint); 55 | while (node != null) { 56 | System.out.print(node.num + " "); 57 | node = node.next; 58 | lastPrint++; 59 | } 60 | tailMap.remove(--lastPrint); 61 | System.out.println(); 62 | } 63 | 64 | } 65 | 66 | public static void main(String[] args) { 67 | // MessageBox only receive 1~N 68 | MessageBox box = new MessageBox(); 69 | 70 | box.receive(2); // - 2 71 | box.receive(1); // 1 2 -> print, trigger is 1 72 | 73 | box.receive(4); // - 4 74 | box.receive(5); // - 4 5 75 | box.receive(7); // - 4 5 - 7 76 | box.receive(8); // - 4 5 - 7 8 77 | box.receive(6); // - 4 5 6 7 8 78 | box.receive(3); // 3 4 5 6 7 8 -> print, trigger is 3 79 | 80 | box.receive(9); // 9 -> print, trigger is 9 81 | 82 | box.receive(10); // 10 -> print, trigger is 10 83 | 84 | box.receive(12); // - 12 85 | box.receive(13); // - 12 13 86 | box.receive(11); // 11 12 13 -> print, trigger is 11 87 | 88 | } 89 | } 90 | ``` -------------------------------------------------------------------------------- /CodeInterviewGuide/Chapter08_Others/Q1031.md: -------------------------------------------------------------------------------- 1 | ## KMP算法 2 | 3 | **题目:** 4 | >给定两个字符串str和match,长度分别为N和M。实现一个算法,如果字符串str中含有子串match,则返回match在str中的开始位置,不含有则返回-1。 5 | 6 | ```java 7 | public class Problem_31_KMPAlgorithm { 8 | 9 | public static int getIndexOf(String s, String m) { 10 | if (s == null || m == null || m.length() < 1 || s.length() < m.length()) { 11 | return -1; 12 | } 13 | char[] ss = s.toCharArray(); 14 | char[] ms = m.toCharArray(); 15 | int si = 0; 16 | int mi = 0; 17 | int[] next = getNextArray(ms); 18 | while (si < ss.length && mi < ms.length) { 19 | if (ss[si] == ms[mi]) { 20 | si++; 21 | mi++; 22 | } else if (next[mi] == -1) { 23 | si++; 24 | } else { 25 | mi = next[mi]; 26 | } 27 | } 28 | return mi == ms.length ? si - mi : -1; 29 | } 30 | 31 | public static int[] getNextArray(char[] ms) { 32 | if (ms.length == 1) { 33 | return new int[] { -1 }; 34 | } 35 | int[] next = new int[ms.length]; 36 | next[0] = -1; 37 | next[1] = 0; 38 | int pos = 2; 39 | int cn = 0; 40 | while (pos < next.length) { 41 | if (ms[pos - 1] == ms[cn]) { 42 | next[pos++] = ++cn; 43 | } else if (cn > 0) { 44 | cn = next[cn]; 45 | } else { 46 | next[pos++] = 0; 47 | } 48 | } 49 | return next; 50 | } 51 | 52 | public static void main(String[] args) { 53 | String str = "abcabcababaccc"; 54 | String match = "ababa"; 55 | System.out.println(getIndexOf(str, match)); 56 | 57 | } 58 | 59 | } 60 | ``` -------------------------------------------------------------------------------- /InternetRecruitingAlgorithmProblems/58TC/Problem Description 2018.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/InternetRecruitingAlgorithmProblems/58TC/Problem Description 2018.md -------------------------------------------------------------------------------- /InternetRecruitingAlgorithmProblems/MEITUAN/pic/Q2Y2017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/InternetRecruitingAlgorithmProblems/MEITUAN/pic/Q2Y2017.png -------------------------------------------------------------------------------- /InternetRecruitingAlgorithmProblems/NETEASE/pic/Q10Y2017.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/InternetRecruitingAlgorithmProblems/NETEASE/pic/Q10Y2017.jpg -------------------------------------------------------------------------------- /InternetRecruitingAlgorithmProblems/NETEASE/pic/Q11Y2017.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/InternetRecruitingAlgorithmProblems/NETEASE/pic/Q11Y2017.jpg -------------------------------------------------------------------------------- /InternetRecruitingAlgorithmProblems/NETEASE/pic/Q1Y2017.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/InternetRecruitingAlgorithmProblems/NETEASE/pic/Q1Y2017.jpg -------------------------------------------------------------------------------- /InternetRecruitingAlgorithmProblems/NETEASE/pic/Q3Y2018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/InternetRecruitingAlgorithmProblems/NETEASE/pic/Q3Y2018.png -------------------------------------------------------------------------------- /InternetRecruitingAlgorithmProblems/NETEASE/pic/Q7Y2017.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/InternetRecruitingAlgorithmProblems/NETEASE/pic/Q7Y2017.jpg -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1001.md: -------------------------------------------------------------------------------- 1 | ## 二维数组中的查找 2 | 3 | **题目:** 4 | 5 | >在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 6 | >>测试用例 7 | >>1. 二位数组中包含要查找的数字(最大值,最下值,中间值); 8 | >>2. 二位数组中没有要查找的值(大于最大,小于最小,中间但是没有); 9 | >>3. 空的二维数组。 10 | 11 | --- 12 | 13 | ### 我的代码 14 | 15 | ```java 16 | public class Solution { 17 | public boolean Find(int [][] array,int target) { 18 | for(int i=0;i首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找结果;如果该数字大于要查找的数字,剔除这个数字所在的列;如果该数字小于要查找的数字,剔除该数字所在的行。也就是说如果要查找的数字不在数组的右上角,则每一次都在数组的查找范围中剔除一行后者一列,这样每一步都可以缩小查找的范围,直到找到要查找的数字,或者查找范围为空。 30 | 31 | ```java 32 | public class Solution { 33 | public boolean Find(int target, int [][] array) { 34 | boolean found=false; 35 | if(array!=null&&array.length>0&&array[0].length>0){ 36 | int row=0; 37 | int column=array[0].length-1; 38 | while(row=0){ 39 | if(array[row][column]==target){ 40 | found=true; 41 | break; 42 | } 43 | else if(array[row][column]输入一个链表,从尾到头打印链表每个节点的值。 6 | >>测试用例 7 | >>1.功能测试(多个结点、单个结点) 8 | >>2.特殊测试(输入的链表头结点指针) 9 | 10 | --- 11 | 12 | ### 我的代码 13 | 14 | ```java 15 | import java.util.ArrayList; 16 | public class Solution { 17 | ArrayList arrayList=new ArrayList(); 18 | public ArrayList printListFromTailToHead(ListNode listNode) { 19 | if(listNode!=null) 20 | { 21 | this.printListFromTailToHead(listNode.next); 22 | arrayList.add(listNode.val); 23 | } 24 | return arrayList; 25 | } 26 | } 27 | ``` 28 | 29 | ### 思路分析 30 | 31 | >遍历链表,遍历的顺序是从头到尾的顺序,输出是从尾到头,这就是典型的“**后进先出**”,用栈实现这种顺序; 32 | >1.每进过一个结点的时候,把该结点放到栈中; 33 | >2.当遍历整个链表后,再从栈顶开始逐个输出结点的值。 34 | 35 | ``` java 36 | /** 37 | * public class ListNode { 38 | * int val; 39 | * ListNode next = null; 40 | * 41 | * ListNode(int val) { 42 | * this.val = val; 43 | * } 44 | * } 45 | * 46 | */ 47 | import java.util.ArrayList; 48 | import java.util.Stack; 49 | public class Solution { 50 | public ArrayList printListFromTailToHead(ListNode listNode) { 51 | Stack l=new Stack();//必须声明栈的类型Integer 52 | ArrayList a=new ArrayList(); 53 | while(listNode!=null){ 54 | l.push(listNode.val); 55 | listNode=listNode.next; 56 | } 57 | while(!l.empty()){ 58 | a.add(l.pop()); 59 | } 60 | return a; 61 | } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1004.md: -------------------------------------------------------------------------------- 1 | ## 重建二叉树 2 | 3 | **题目:** 4 | 5 | >输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 6 | >>测试用例 7 | >>1. 普通二叉树(完全二叉树,不完全二叉树); 8 | >>2. 特殊二叉树(没有右子结点,没有左子结点,只有一个结点); 9 | >>3. 树为NULL,输入前序遍历和中序遍历不匹配。 10 | 11 | ------------------------------------------------------------------------------------------------- 12 | 13 | ### 思路分析 14 | 15 | >在二叉树的前序遍序列中,第一个数字总是树的根结点的值。但在中序遍历序列中,根节点的值在序列的中间,左子树的结点在根节点的值的左边,而右子树的结点的值在根结点值的右边。 16 | ```java 17 | /** 18 | * Definition for binary tree 19 | * public class TreeNode { 20 | * int val; 21 | * TreeNode left; 22 | * TreeNode right; 23 | * TreeNode(int x) { val = x; } 24 | * } 25 | */ 26 | public class Solution { 27 | public TreeNode reConstructBinaryTree(int [] pre,int [] in) { 28 | TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1); 29 | return root; 30 | } 31 | //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6} 32 | private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) { 33 | 34 | if(startPre>endPre||startIn>endIn) 35 | return null; 36 | TreeNode root=new TreeNode(pre[startPre]); 37 | 38 | for(int i=startIn;i<=endIn;i++) 39 | if(in[i]==pre[startPre]){ 40 | root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1); 41 | root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn); 42 | } 43 | 44 | return root; 45 | } 46 | } 47 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1005.md: -------------------------------------------------------------------------------- 1 | ## 用两个栈实现队列 2 | 3 | **题目:** 4 | >用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。 5 | >>测试用例 6 | >>1. 往空的队列里添加、删除元素; 7 | >>2, 往非空的队列里添加、删除元素; 8 | >>3. 连续删除元素直至队空。 9 | 10 | --- 11 | 12 | ### 我的代码 13 | 14 | ```java 15 | import java.util.Stack; 16 | public class Solution { 17 | Stack stack1 = new Stack(); 18 | Stack stack2 = new Stack(); 19 | int count=0; 20 | public void push(int node) { 21 | stack1.push(node); 22 | count++; 23 | } 24 | public int pop() { 25 | if(count<=0) return 0; 26 | for(int i=count;i>0;i--){ 27 | stack2.push(stack1.pop()); 28 | } 29 | int k=stack2.pop(); 30 | count--; 31 | for(int i=count;i>0;i--){ 32 | stack1.push(stack2.pop()); 33 | } 34 | return k; 35 | } 36 | } 37 | ``` 38 | 39 | ### 思路分析 40 | 41 | ```java 42 | import java.util.Stack; 43 | public class Solution { 44 | Stack stack1 = new Stack(); 45 | Stack stack2 = new Stack(); 46 | public void push(int node) { 47 | stack1.push(node); 48 | public int pop() { 49 | //判断栈2中是否还有元素 50 | if(stack2.size()<=0){ //栈2中没有元素则把栈1中的元素全部压入栈2 51 | while(stack1.size()>0){ 52 | stack2.push(stack1.pop()); 53 | } 54 | } 55 | return stack2.pop(); //栈2中如果有元素直接出栈 56 | } 57 | } 58 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1006.md: -------------------------------------------------------------------------------- 1 | ## 旋转数组的最小数字 2 | 3 | **题目:** 4 | >把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 5 | >>测试用例 6 | >>1. 功能测试(输入的数组是升序排序数组的一个旋转,数组中有重复数字或者没有重复数字); 7 | >>2. 边界值测试(输入的数组是一个升序排序的数组、只包含一个数字的数组); 8 | >>3. 特殊输入测试(输入NULL指针)。 9 | 10 | --- 11 | 12 | ### 我的代码 13 | 14 | ```java 15 | import java.util.Arrays; 16 | public class Solution { 17 | public int minNumberInRotateArray(int [] array) { 18 | if(array.length==0) 19 | return 0; 20 | else{ 21 | Arrays.sort(array);//对数组进行升序排序,第一个元素为最小的元素 22 | return array[0]; 23 | } 24 | } 25 | } 26 | ``` 27 | 28 | ### 思路分析 29 | 30 | ```java 31 | import java.util.ArrayList; 32 | public class Solution { 33 | public int minNumberInRotateArray(int [] array) { 34 | if(array.length<=0) return 0; 35 | int index1=0; 36 | int index2=array.length-1; 37 | int indexMid=index1; 38 | while(array[index1]>=array[index2]){ 39 | if(index2-index1==1){ 40 | indexMid=index2; 41 | break; 42 | } 43 | indexMid = (index1+index2)/2; 44 | if(array[index1]==array[index2]&&array[indexMid]==array[index1]){ 45 | return MinInOrder(array,index1,index2); 46 | } 47 | if(array[indexMid]>=array[index1]) 48 | index1=indexMid; 49 | else if(array[indexMid]<=array[index2]) 50 | index2=indexMid; 51 | } 52 | return array[indexMid]; 53 | } 54 | 55 | public int MinInOrder(int[] array,int index1,int index2){ 56 | int result = array[index1]; 57 | for(int i=index1+1;i<=index2;i++){ 58 | if(result>array[i]) 59 | result=array[i]; 60 | } 61 | return result; 62 | } 63 | } 64 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1007.md: -------------------------------------------------------------------------------- 1 | ## 斐波那契数列 2 | 3 | **题目:** 4 | >大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39 5 | 6 | --- 7 | 8 | ### 题目分析 9 | 10 | ```java 11 | public class Solution { 12 | public int Fibonacci(int n) { 13 | int sum0=0,sum1=1,sum2=1; 14 | if(n<=0) 15 | return 0; 16 | else if(n<=1) 17 | return 1; 18 | else{ 19 | for(int i=1;i<=n-1;i++){ 20 | sum2=sum0+sum1; 21 | sum0=sum1; 22 | sum1=sum2; 23 | } 24 | return sum1; 25 | } 26 | } 27 | } 28 | ``` 29 | 30 | ## 变态跳台阶 31 | 32 | **题目:** 33 | >一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 34 | 35 | --- 36 | 37 | ### 题目分析 38 | 39 | ```java 40 | public class Solution { 41 | public int JumpFloorII(int target) { 42 | if(target==0) 43 | return 0; 44 | if(target==1) 45 | return 1; 46 | return JumpFloorII(target-1)*2; 47 | } 48 | } 49 | ``` 50 | 51 | ## 矩形覆盖 52 | 53 | **题目:** 54 | >我们可以用2\*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2\*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 55 | 56 | --- 57 | 58 | ### 题目分析 59 | 60 | ```java 61 | public class Solution { 62 | public int RectCover(int target) { 63 | if(target==0) 64 | return 0; 65 | if(target==1) 66 | return 1; 67 | if(target==2) 68 | return 2; 69 | return RectCover(target-1)+RectCover(target-2); 70 | 71 | } 72 | } 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1008.md: -------------------------------------------------------------------------------- 1 | ## 二进制中1的个数 2 | 3 | **题目:** 4 | >输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 5 | >>测试用例 6 | >>1. 正数(包括边界值1、0x7FFFFFF); 7 | >>2. 负数(包括边界值0x80000000,0xFFFFFFFF); 8 | >>3. 0; 9 | 10 | --- 11 | 12 | ### 思路分析 13 | 14 | >首先把n和1做与运算,判断n的最低的最低位是不是为1。 15 | >接着把1左移一位得到2,再和n做与运算...... 16 | >每次都能判断n的其中一位是不是1. 17 | 18 | ```java 19 | public class Solution { 20 | public int NumberOf1(int n) { 21 | int count=0; 22 | int bit=1; 23 | while(bit!=0){ 24 | if((n&bit)!=0) count++; 25 | bit=bit<<1; 26 | } 27 | return count; 28 | } 29 | } 30 | ``` 31 | 32 | ### 补充知识 33 | 34 | ```java 35 | `>>`(右移,符号位填充高位)、`>>>`(用0填充高位) 36 | ``` 37 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1009.md: -------------------------------------------------------------------------------- 1 | ## 数值的整数次方 2 | 3 | **题目:** 4 | >给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public double Power(double base, int exponent) { 13 | double i=1.0; 14 | if(exponent>0){ 15 | for(int j=0;j功能测试,边界条件,负面测试以确保代码的完整性 32 | >错误处理方法: 33 | >1. 用返回值来告知是否出错; 34 | >2. 设置一个全局变量; 35 | >3. 异常; 36 | 37 | ```java 38 | public class Solution { 39 | public double Power(double base, int exponent) { 40 | //判断有可能出错的试例 41 | if(base==0.0&&exponent<0){ 42 | return 0.0; 43 | } 44 | if(exponent==0){ 45 | return 1.0; 46 | } 47 | double answer=1.0; 48 | if(exponent>0){ 49 | for(int i=0;i0){ 75 | mul=exponent; 76 | } 77 | double answer=1.0; 78 | while(mul!=0){ 79 | if((mul&1)==1){ 80 | answer*=base; 81 | } 82 | base*=base; 83 | mul>>=1; 84 | } 85 | return exponent>0?answer:(1/answer); 86 | } 87 | } 88 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1011.md: -------------------------------------------------------------------------------- 1 | ## 在O(1)时间删除链表节点 2 | 3 | **题目:** 4 | >给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点。 5 | 6 | --- 7 | 8 | ### 思路解析 9 | 10 | ```java 11 | /* 12 | public class ListNode{ 13 | int val; 14 | ListNode next=null; 15 | ListNode(int val){ 16 | this.val=val; 17 | } 18 | } 19 | */ 20 | public class DeleteNode { 21 | private void Delete(ListNode pListHead,ListNode pToBeDeleted){ 22 | if(pListHead==null||pToBeDeleted==null) 23 | return; 24 | if(pToBeDeleted.next!=null){ 25 | ListNode pNext=pToBeDeleted.next; 26 | pToBeDeleted.val=pNext.val;//将下一个结点的值替换本结点的值 27 | pToBeDeleted.next=pNext.next; 28 | pNext=null; 29 | } 30 | else if(pListHead==pToBeDeleted){ 31 | pToBeDeleted=null; 32 | pListHead=null; 33 | } 34 | else{ 35 | ListNode pNode=pListHead; 36 | while(pNode.next!=pToBeDeleted){ 37 | pNode=pNode.next; 38 | } 39 | pNode.next=null; 40 | pToBeDeleted=null; 41 | } 42 | } 43 | //main函数测试 44 | public static void main(String[] args){ 45 | ListNode origin=new ListNode(0); 46 | DeleteNode d=new DeleteNode(); 47 | //对链表各个结点赋值 48 | ListNode temp=origin; 49 | for(int i=1;i<10;i++){ 50 | temp.next=new ListNode(i); 51 | temp=temp.next; 52 | } 53 | ListNode del=origin.next.next.next.next;//定义要删除的链表 54 | d.Delete(origin, del); 55 | while(origin!=null){ 56 | System.out.println(origin.val); 57 | origin=origin.next; 58 | } 59 | } 60 | } 61 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1012.md: -------------------------------------------------------------------------------- 1 | ## 调整数组顺序使奇数位于偶数前面 2 | 3 | **题目:** 4 | >输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,**并保证奇数和奇数,偶数和偶数之间的相对位置不变**。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public void reOrderArray(int [] array) { 13 | int j=0,k=0,m=0,n=0; 14 | int [] a_new=new int[array.length]; 15 | for(int i=0;i输入一个链表,输出该链表中倒数第k个结点。 5 | >>测试用例 6 | >>1. 功能测试时(第k个结点在链表的中间,第k个结点是链表的头结点,第k个结点是链表的尾节点); 7 | >>2. 特殊输入测试(链表头结点为NULL指针,链表的结点总数少于k,k等于0); 8 | 9 | --- 10 | 11 | ### 我的代码 12 | 13 | ```java 14 | /* 15 | public class ListNode { 16 | int val; 17 | ListNode next = null; 18 | ListNode(int val) { 19 | this.val = val; 20 | } 21 | }*/ 22 | public class Solution { 23 | public ListNode FindKthToTail(ListNode head,int k) { 24 | int j=hasNext(head); 25 | if(k>j) 26 | return null; 27 | else 28 | return Next(head,j-k); 29 | } 30 | public int hasNext(ListNode l){ 31 | int n=0; 32 | if(l==null) 33 | return 0; 34 | else{ 35 | n=hasNext(l.next)+1; 36 | } 37 | return n; 38 | } 39 | public ListNode Next(ListNode node,int m){ 40 | ListNode node2; 41 | if(m==0) 42 | return node; 43 | else{ 44 | node2=Next(node.next,--m); 45 | } 46 | return node2; 47 | } 48 | } 49 | ``` 50 | 51 | ### 思路分析 52 | 53 | >定义两个结点标识P1,P2,P1从链表的头结点开始遍历向前走k-1,P2保持不变; 54 | >从第k步开始,P2也开始遍历; 55 | >当P1走完,P2则走到倒数第k个结点。 56 | ```java 57 | public class Solution { 58 | public ListNode FindKthToTail(ListNode head,int k) { 59 | if(head==null||k<=0) return null; 60 | ListNode P1=head; 61 | ListNode P2=head; 62 | for(int i=0;i输入一个链表,反转链表后,输出链表的所有元素。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public ListNode ReverseList(ListNode head) { 13 | if(head==null) 14 | return head; 15 | ListNode newnode=head; 16 | ListNode pre=null; 17 | ListNode current=null; 18 | while(newnode!=null){ 19 | current=newnode.next; 20 | newnode.next=pre; 21 | pre=newnode; 22 | newnode=current; 23 | } 24 | return pre; 25 | } 26 | } 27 | ``` 28 | 29 | ### 思路分析 30 | 31 |

32 | 33 | ```java 34 | public class Solution { 35 | public ListNode ReverseList(ListNode head) { 36 | ListNode pReversedHead=null; 37 | ListNode pNode=head; 38 | ListNode pPrev=null; 39 | while(pNode!=null){ 40 | ListNode pNext=pNode.next; 41 | if(pNext==null) 42 | pReversedHead=pNode; 43 | pNode.next=pPrev; 44 | pPrev=pNode; 45 | pNode=pNext; 46 | } 47 | return pReversedHead; 48 | } 49 | } 50 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1015.md: -------------------------------------------------------------------------------- 1 | ## 合并两个排序的链表 2 | 3 | **题目:** 4 | >输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 5 | >>测试用例: 6 | >>1. 功能测试(输入的两个链表有多个结点,结点的值互不相同或者存在值相等的多个结点); 7 | >>2. 特殊输入测试(两个链表的一个或者两个头结点为null指针、两个链表中只有一个结点)。 8 | 9 | --- 10 | 11 | ### 我的代码 12 | 13 | ```java 14 | /* 15 | public class ListNode { 16 | int val; 17 | ListNode next = null; 18 | 19 | ListNode(int val) { 20 | this.val = val; 21 | } 22 | }*/ 23 | public class Solution { 24 | public ListNode Merge(ListNode list1,ListNode list2) { 25 | if(list1==null) 26 | return list2; 27 | else if(list2==null) 28 | return list1; 29 | ListNode l=null; 30 | if(list1.val<=list2.val){ 31 | l=list1; 32 | l.next=Merge(list1.next,list2); 33 | } 34 | else{ 35 | l=list2; 36 | l.next=Merge(list1,list2.next); 37 | } 38 | return l; 39 | } 40 | } 41 | ``` 42 | 43 | ### 思路分析 44 | 45 |

46 | 47 | ``` java 48 | public class Solution { 49 | public ListNode Merge(ListNode list1,ListNode list2) { 50 | if(list1==null) return list2; 51 | if(list2==null) return list1; 52 | ListNode pHead=null; 53 | if(list1.val输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)。 5 | >1. 功能测试(树A和树B都是普通的二叉树,树B是或者不是树A的子结构) 6 | >2. 特殊输入测试(两棵二叉树的一个或者两个根节点为null指针、二叉树的所有结点都没有左子树或者右子树) 7 | 8 | --- 9 | 10 | ### 我的代码 11 | 12 | ```java 13 | public class Solution { 14 | public boolean HasSubtree(TreeNode root1,TreeNode root2) { 15 | if(root2==null) return false; 16 | if(root1==null && root2!=null) return false; 17 | boolean flag = false; 18 | if(root1.val==root2.val){ 19 | flag = isSubTree(root1,root2); 20 | } 21 | if(!flag){ 22 | flag = HasSubtree(root1.left, root2); 23 | if(!flag){ 24 | flag = HasSubtree(root1.right, root2); 25 | } 26 | } 27 | return flag; 28 | } 29 | private boolean isSubTree(TreeNode root1, TreeNode root2) { 30 | if(root2==null) return true; 31 | if(root1==null && root2!=null) return false; 32 | if(root1.val==root2.val){ 33 | return isSubTree(root1.left, root2.left) && isSubTree(root1.right, root2.right); 34 | } 35 | return false; 36 | } 37 | } 38 | ``` 39 | 40 | ### 思路分析 41 | 42 |

43 | 44 | ```java 45 | public class Solution { 46 | public boolean HasSubtree(TreeNode root1,TreeNode root2) { 47 | boolean result=false; 48 | if(root1!=null&&root2!=null){ 49 | if(root1.val==root2.val) 50 | result=DoesSubtree(root1,root2); 51 | if(!result) 52 | result=HasSubtree(root1.left,root2); 53 | if(!result) 54 | result=HasSubtree(root1.right,root2); 55 | } 56 | return result; 57 | } 58 | public boolean DoesSubtree(TreeNode root1,TreeNode root2){ 59 | if(root2==null) return true; 60 | if(root1==null) return false; 61 | if(root1.val!=root2.val) return false; 62 | return DoesSubtree(root1.left,root2.left)&&DoesSubtree(root1.right,root2.right); 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1017.md: -------------------------------------------------------------------------------- 1 | ## 二叉树的镜像 2 | 3 | **题目:** 4 | >操作给定的二叉树,将其变换为源二叉树的镜像。 5 | 二叉树的镜像定义:源二叉树 6 | ``` 7 | 8 8 | / \ 9 | 6 10 10 | / \ / \ 11 | 5 7 9 11 12 | 镜像二叉树 13 | 8 14 | / \ 15 | 10 6 16 | / \ / \ 17 | 11 9 7 5 18 | ``` 19 | 20 | --- 21 | 22 | ### 思路分析 23 | 24 |

25 | 26 | ```java 27 | public class Solution { 28 | public void Mirror(TreeNode root) { 29 | if(root==null) return; 30 | if(root.left==null&&root.right==null) return; 31 | TreeNode temp=root.left; 32 | root.left=root.right; 33 | root.right=temp; 34 | if(root.left!=null) 35 | Mirror(root.left); 36 | if(root.right!=null) 37 | Mirror(root.right); 38 | } 39 | } 40 | ``` 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1021.md: -------------------------------------------------------------------------------- 1 | ## 从上往下打印二叉树 2 | 3 | **题目:** 4 | >从上往下打印出二叉树的每个节点,同层节点从左至右打印。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | import java.util.ArrayList; 12 | /** 13 | public class TreeNode { 14 | int val = 0; 15 | TreeNode left = null; 16 | TreeNode right = null; 17 | public TreeNode(int val) { 18 | this.val = val; 19 | } 20 | } 21 | */ 22 | public class Solution { 23 | ArrayList list=new ArrayList(); 24 | public ArrayList PrintFromTopToBottom(TreeNode root) { 25 | if(root!=null) 26 | list.add(root.val); 27 | print(root); 28 | return list; 29 | } 30 | public void print(TreeNode root){ 31 | if(root!=null){ 32 | if(root.left!=null) 33 | list.add(root.left.val); 34 | if(root.right!=null) 35 | list.add(root.right.val); 36 | print(root.left); 37 | print(root.right); 38 | } 39 | } 40 | } 41 | ``` 42 | 43 | ### 思路分析 44 | 45 |

46 | 47 | ```java 48 | public class Solution { 49 | public ArrayList PrintFromTopToBottom(TreeNode root) { 50 | ArrayList TreeNodeList=new ArrayList(); 51 | ArrayList levelTreeNode=new ArrayList(); 52 | if(root==null) return levelTreeNode; 53 | TreeNodeList.add(root); 54 | while(TreeNodeList.size()>0){ 55 | TreeNode pNode=TreeNodeList.remove(0); 56 | levelTreeNode.add(pNode.val); 57 | if(pNode.left!=null) 58 | TreeNodeList.add(pNode.left); 59 | if(pNode.right!=null) 60 | TreeNodeList.add(pNode.right); 61 | } 62 | return levelTreeNode; 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1029.md: -------------------------------------------------------------------------------- 1 | ## 连续子数组的最大和 2 | 3 | **题目:** 4 | >HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1) 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public int FindGreatestSumOfSubArray(int[] array) { 13 | if(array.length==0||array==null) 14 | return 0; 15 | int thisSum=0,maxSum=array[0]; 16 | for(int j=0;jmaxSum) 19 | maxSum=thisSum; 20 | else if(thisSum<0) 21 | thisSum=0; 22 | } 23 | return maxSum; 24 | } 25 | } 26 | ``` 27 | 28 | ### 思路分析 29 | 30 | - **举例分析数组的规律** 31 | 32 |

33 | 34 |

35 | 36 | ```java 37 | public class Solution { 38 | boolean g_InvalidInput=false; 39 | public int FindGreatestSumOfSubArray(int[] array) { 40 | if(array==null||array.length<=0){ 41 | g_InvalidInput=true; 42 | return 0; 43 | } 44 | g_InvalidInput=false; 45 | int nCurSum=0; 46 | int nGreatestSum=0x80000000; 47 | for(int i=0;inGreatestSum) 53 | nGreatestSum=nCurSum; 54 | } 55 | return nGreatestSum; 56 | 57 | } 58 | } 59 | ``` 60 | - **应用动态规划** 61 | 62 |

63 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1030.md: -------------------------------------------------------------------------------- 1 | ## 整数中1出现的次数(从1到n整数中1出现的次数) 2 | 3 | **题目:** 4 | >求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数. 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public int NumberOf1Between1AndN_Solution(int n) { 13 | if(n<=0) 14 | return 0; 15 | int count=0; 16 | for(int i=1;i<=n;i++){ 17 | int shang=i; 18 | int yushu=shang%10; 19 | while(shang!=0){ 20 | if(yushu==1) 21 | count++; 22 | shang=shang/10; 23 | yushu=shang%10; 24 | } 25 | } 26 | return count; 27 | } 28 | } 29 | ``` 30 | 31 | ### 思路分析 32 | 33 |

34 | 35 | ```java 36 | public class Solution { 37 | public int NumberOf1Between1AndN_Solution(int n) { 38 | int count = 0;//1的个数 39 | int i = 1;//当前位 40 | int current = 0,after = 0,before = 0; 41 | while((n/i)!= 0){ 42 | current = (n/i)%10; //高位数字 43 | before = n/(i*10); //当前位数字 44 | after = n-(n/i)*i; //低位数字 45 | //如果为0,出现1的次数由高位决定,等于高位数字 * 当前位数 46 | if (current == 0) 47 | count += before*i; 48 | //如果为1,出现1的次数由高位和低位决定,高位*当前位+低位+1 49 | else if(current == 1) 50 | count += before * i + after + 1; 51 | //如果大于1,出现1的次数由高位决定,//(高位数字+1)* 当前位数 52 | else{ 53 | count += (before + 1) * i; 54 | } 55 | //前移一位 56 | i = i*10; 57 | } 58 | return count; 59 | } 60 | } 61 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1031.md: -------------------------------------------------------------------------------- 1 | ## 把数组排成最小的数 2 | 3 | **题目:** 4 | >输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.Comparator; 14 | public class Solution { 15 | public String PrintMinNumber(int [] numbers) { 16 | int n; 17 | String s=""; 18 | ArrayList list= new ArrayList(); 19 | n=numbers.length; 20 | for(int i=0;i(){ 25 | public int compare(Integer str1,Integer str2){ 26 | String s1=str1+""+str2; 27 | String s2=str2+""+str1; 28 | return s1.compareTo(s2); 29 | } 30 | }); 31 | 32 | for(int j:list){ 33 | s+=j; 34 | } 35 | return s; 36 | } 37 | } 38 | ``` 39 | 40 | ### 思路分析 41 | 42 | ```java 43 | * 解题思路: 44 | * 先将整型数组转换成String数组,然后将String数组排序,最后将排好序的字符串数组拼接出来。关键就是制定排序规则。 45 | * 排序规则如下: 46 | * 若ab > ba 则 a > b, 47 | * 若ab < ba 则 a < b, 48 | * 若ab = ba 则 a = b; 49 | * 解释说明: 50 | * 比如 "3" < "31"但是 "331" > "313",所以要将二者拼接起来进行比较 51 | import java.util.ArrayList; 52 | import java.util.*; 53 | public class Solution { 54 | public String PrintMinNumber(int [] numbers) { 55 | if(numbers == null || numbers.length == 0) return ""; 56 | int len = numbers.length; 57 | String[] str = new String[len]; 58 | StringBuilder sb = new StringBuilder(); 59 | for(int i = 0; i < len; i++){ 60 | str[i] = String.valueOf(numbers[i]); 61 | } 62 | Arrays.sort(str,new Comparator(){ 63 | @Override 64 | public int compare(String s1, String s2) { 65 | String c1 = s1 + s2; 66 | String c2 = s2 + s1; 67 | return c1.compareTo(c2); 68 | } 69 | }); 70 | for(int i = 0; i < len; i++){ 71 | sb.append(str[i]); 72 | } 73 | return sb.toString(); 74 | } 75 | } 76 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1032.md: -------------------------------------------------------------------------------- 1 | ## 丑数 2 | 3 | **题目:** 4 | >把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | import java.util.*; 12 | public class Solution { 13 | public int GetUglyNumber_Solution(int index) { 14 | if(index==0)return 0; 15 | int n=1,ugly=1,min; 16 | Queue q2=new LinkedList(); 17 | Queue q3=new LinkedList(); 18 | Queue q5=new LinkedList(); 19 | q2.add(2);q3.add(3);q5.add(5); 20 | while(n!=index){ 21 | ugly=Math.min(q2.peek(),Math.min(q3.peek(),q5.peek())); 22 | if(ugly==q2.peek()){ 23 | q2.add(ugly*2);q3.add(ugly*3);q5.add(ugly*5);q2.poll(); 24 | } 25 | if(ugly==q3.peek()){ 26 | q3.add(ugly*3);q5.add(ugly*5);q3.poll(); 27 | } 28 | if(ugly==q5.peek()){ 29 | q5.add(ugly*5);q5.poll(); 30 | } 31 | n++; 32 | } 33 | return ugly; 34 | } 35 | } 36 | ``` 37 | 38 | ### 思路分析 39 | 40 | ```java 41 | public class Solution { 42 | public int GetUglyNumber_Solution(int index) { 43 | if(index<=0) return 0; 44 | int[] pUglyNumbers= new int[index]; 45 | pUglyNumbers[0]=1; 46 | int nextUglyIndex=1; 47 | int[] pMultiply2=pUglyNumbers; 48 | int[] pMultiply3=pUglyNumbers; 49 | int[] pMultiply5=pUglyNumbers; 50 | int i=0; 51 | int j=0; 52 | int k=0; 53 | while(nextUglyIndex在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public int FirstNotRepeatingChar(String str) { 13 | if(str==null) 14 | return -1; 15 | char[] str_char=str.toCharArray(); 16 | int m=-1; 17 | for(int i=0;i
39 | 40 | ```java 41 | public class Solution { 42 | public int FirstNotRepeatingChar(String str) { 43 | if(str==null) return -1; 44 | char[] pString=str.toCharArray(); 45 | int tablesize=256; 46 | int[] hashTable=new int[tablesize]; 47 | int[] hashTableIndex=new int[tablesize]; 48 | for(int i=0;i
67 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1035.md: -------------------------------------------------------------------------------- 1 | ## 两个链表的第一个公共结点 2 | 3 | **题目:** 4 | >输入两个链表,找出它们的第一个公共结点。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 |

11 | 12 | ```java 13 | /* 14 | public class ListNode { 15 | int val; 16 | ListNode next = null; 17 | 18 | ListNode(int val) { 19 | this.val = val; 20 | } 21 | }*/ 22 | public class Solution { 23 | public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { 24 | int nLength1=GetListLength(pHead1); 25 | int nLength2=GetListLength(pHead2); 26 | int nLengthDif=nLength1-nLength2; 27 | ListNode pListHeadLong=pHead1; 28 | ListNode pListHeadShort=pHead2; 29 | if(nLength2>nLength1){ 30 | pListHeadLong=pHead2; 31 | pListHeadShort=pHead1; 32 | nLengthDif=nLength2-nLength1; 33 | } 34 | 35 | for(int i=0;i输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 |

11 | 12 | ```java 13 | /* 14 | public class TreeNode { 15 | int val = 0; 16 | TreeNode left = null; 17 | TreeNode right = null; 18 | public TreeNode(int val) { 19 | this.val = val; 20 | } 21 | };*/ 22 | public class Solution { 23 | public int TreeDepth(TreeNode pRoot) 24 | { 25 | if(pRoot==null) 26 | return 0; 27 | if(pRoot.left==null&&pRoot.right==null) 28 | return 1; 29 | int i=0,j=0; 30 | i=1+TreeDepth(pRoot.left); 31 | j=1+TreeDepth(pRoot.right); 32 | if(i>j) 33 | return i; 34 | return j; 35 | } 36 | } 37 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1038.md: -------------------------------------------------------------------------------- 1 | ## 平衡二叉树 2 | 3 | **题目:** 4 | >输入一棵二叉树,判断该二叉树是否是平衡二叉树。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | //后续遍历时,遍历到一个节点,其左右子树已经遍历 依次自底向上判断,每个节点只需要遍历一次 13 | 14 | private boolean isBalanced=true; 15 | public boolean IsBalanced_Solution(TreeNode root) { 16 | 17 | getDepth(root); 18 | return isBalanced; 19 | } 20 | public int getDepth(TreeNode root){ 21 | if(root==null) 22 | return 0; 23 | int left=getDepth(root.left); 24 | int right=getDepth(root.right); 25 | 26 | if(Math.abs(left-right)>1){ 27 | isBalanced=false; 28 | } 29 | return right>left ?right+1:left+1; 30 | 31 | } 32 | } 33 | ``` 34 | 35 | ### 思路分析 36 | 37 |

38 | 39 | ```java 40 | public class Solution { 41 | public boolean IsBalanced_Solution(TreeNode root){ 42 | int depth=0; 43 | return IsBalanced_Solution(root,depth); 44 | } 45 | public boolean IsBalanced_Solution(TreeNode root,int pDepth) { 46 | if(root==null){ 47 | pDepth=0; 48 | return true; 49 | } 50 | int left=0; 51 | int right=0; 52 | if(IsBalanced_Solution(root.left,left)&&IsBalanced_Solution(root.right,right)){ 53 | int diff=left-right; 54 | if(diff<=1&&diff>=-1){ 55 | pDepth=1+(left>right?left:right); 56 | return true; 57 | } 58 | } 59 | return false; 60 | } 61 | } 62 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1039.md: -------------------------------------------------------------------------------- 1 | ## 数组中只出现一次的数字 2 | 3 | **题目:** 4 | >一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | //num1,num2分别为长度为1的数组。传出参数 12 | //将num1[0],num2[0]设置为返回结果 13 | public class Solution { 14 | public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) { 15 | if(array.length==0){ 16 | } 17 | int[] num=new int[2]; 18 | int m=0; 19 | for(int i=0;i
41 | 42 | ```java 43 | //num1,num2分别为长度为1的数组。传出参数 44 | //将num1[0],num2[0]设置为返回结果 45 | public class Solution { 46 | public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) { 47 | if(array==null||array.length<2) return; 48 | int resultExclusiveOR=0; 49 | for(int i=0;i>1; 66 | ++indexBit; 67 | } 68 | return indexBit; 69 | } 70 | 71 | boolean IsBit1(int num,int indexBit){ 72 | num=num>>indexBit; 73 | if((num&1)==1) return true; 74 | return false; 75 | } 76 | } 77 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1041.md: -------------------------------------------------------------------------------- 1 | ## 和为S的两个数字 2 | 3 | **题目:** 4 | >输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。 5 | 输出描述: 6 | 对应每个测试案例,输出两个数,小的先输出 7 | 8 | --- 9 | 10 | ### 我的代码 11 | 12 | ```java 13 | import java.util.ArrayList; 14 | public class Solution { 15 | public ArrayList FindNumbersWithSum(int [] array,int sum) { 16 | ArrayList l=new ArrayList(); 17 | if(array.length<2) 18 | return l; 19 | 20 | boolean flag=false; 21 | for(int i=0;i
43 | 44 |

45 | 46 | ```java 47 | import java.util.ArrayList; 48 | public class Solution { 49 | public ArrayList FindNumbersWithSum(int [] array,int sum) { 50 | ArrayList listOfSum=new ArrayList(); 51 | if(array.length<1||array==null) return listOfSum; 52 | int ahead=array.length-1; 53 | int behind=0; 54 | while(ahead>behind){ 55 | int curSum=array[ahead]+array[behind]; 56 | if(curSum==sum){ 57 | listOfSum.add(array[behind]); 58 | listOfSum.add(array[ahead]); 59 | return listOfSum; 60 | } 61 | else if(curSum>sum){ 62 | ahead--; 63 | } 64 | else 65 | behind++; 66 | } 67 | return listOfSum; 68 | } 69 | } 70 | ``` 71 | 72 | 73 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1042.md: -------------------------------------------------------------------------------- 1 | ## 左旋转字符串 2 | 3 | **题目:** 4 | >汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它! 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public String LeftRotateString(String str,int n) { 13 | char[] arr = str.toCharArray(); 14 | StringBuilder sb = new StringBuilder(); 15 | if(str.length() == 0) return sb.toString(); 16 | StringBuilder old = new StringBuilder(str); 17 | for(int i = 0; i< n;++i){ 18 | sb.append(arr[i]); 19 | } 20 | old.delete(0,n); 21 | return (old.append(sb.toString())).toString(); 22 | } 23 | } 24 | ``` 25 | 26 | ### 思路分析 27 | 28 |

29 | 30 | ```java 31 | public class Solution { 32 | public String LeftRotateString(String str,int n) { 33 | char[] charOfStr=str.toCharArray(); 34 | if(str!=null){ 35 | int nLength=charOfStr.length; 36 | if(nLength>0&&n>0&&nLL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public boolean isContinuous(int [] numbers) { 13 | if(numbers.length<5) 14 | return false; 15 | int[]d = new int[14]; 16 | d[0] = -5; 17 | int len = numbers.length; 18 | int max = -1; 19 | int min = 14; 20 | for(int i =0;i1){ 26 | return false; 27 | } 28 | if(numbers[i] >max){ 29 | max = numbers[i]; 30 | } if(numbers[i]
46 | 47 | ```java 48 | import java.util.*; 49 | public class Solution { 50 | public boolean isContinuous(int [] numbers) { 51 | if(numbers==null||numbers.length<=0) return false; 52 | Arrays.sort(numbers); 53 | int numberOfZero=0; 54 | int numberOfGap=0; 55 | for(int i=0;inumberOfZero)?false:true; 67 | } 68 | } 69 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1045.md: -------------------------------------------------------------------------------- 1 | ## 孩子们的游戏(圆圈中最后剩下的数) 2 | 3 | **题目:** 4 | >每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1) 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | public int LastRemaining_Solution(int n, int m) { 13 | if(n<1||m<1) return -1; 14 | int[] array = new int[n]; 15 | int i = -1,step = 0, count = n; 16 | while(count>0){ //跳出循环时将最后一个元素也设置为了-1 17 | i++; //指向上一个被删除对象的下一个元素。 18 | if(i>=n) i=0; //模拟环。 19 | if(array[i] == -1) continue; //跳过被删除的对象。 20 | step++; //记录已走过的。 21 | if(step==m) { //找到待删除的对象。 22 | array[i]=-1; 23 | step = 0; 24 | count--; 25 | } 26 | } 27 | return i;//返回跳出循环时的i,即最后一个被设置为-1的元素 28 | } 29 | } 30 | ``` 31 | 32 | ### 思路分析 33 | 34 |

35 | 36 |

37 | 38 |

39 | 40 | 41 | ```java 42 | public class Solution { 43 | public int LastRemaining_Solution(int n, int m) { 44 | if(n<1||m<1) return -1; 45 | int last=0; 46 | for(int i=2;i<=n;i++){ 47 | last=(last+m)%i; 48 | } 49 | return last; 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1046.md: -------------------------------------------------------------------------------- 1 | ## 求1+2+3+...+n 2 | 3 | **题目:** 4 | >求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C). 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | ```java 11 | public class Solution { 12 | public int Sum_Solution(int n) { 13 | int sum = n; 14 | boolean ans = (n>0)&&((sum+=Sum_Solution(n-1))>0); 15 | return sum; 16 | } 17 | } 18 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1047.md: -------------------------------------------------------------------------------- 1 | ## 不用加减乘除做加法 2 | 3 | **题目:** 4 | >写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 |

11 | 12 |

13 | 14 | 15 | ```java 16 | public class Solution { 17 | public int Add(int num1,int num2) { 18 | int sum=0; 19 | int carry=0; 20 | do{ 21 | sum=num1^num2; 22 | carry=(num1&num2)<<1; 23 | num1=sum; 24 | num2=carry; 25 | } 26 | while(num2!=0); 27 | return num1; 28 | } 29 | } 30 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1050.md: -------------------------------------------------------------------------------- 1 | ## 构建乘积数组 2 | 3 | **题目:** 4 | > 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | import java.util.ArrayList; 12 | public class Solution { 13 | public int[] multiply(int[] A) { 14 | int[] B=new int[A.length]; 15 | if(A.length<=0) 16 | return B; 17 | for(int i=0;i= 0; j--){ 48 | temp *= A[j+1]; 49 | B[j] *= temp; 50 | } 51 | } 52 | return B; 53 | } 54 | } 55 | ``` 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1051.md: -------------------------------------------------------------------------------- 1 | ## 正则表达式匹配 2 | 3 | **题目:** 4 | >请实现一个函数用来匹配包括`.`和`*`的正则表达式。模式中的字符'.'表示任意一个字符,而`*`表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab`*`ac`*`a"匹配,但是与"aa.a"和"ab`*`a"均不匹配 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | >当模式中的第二个字符不是`*`时: 11 | 1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。 12 | 2、如果 字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。 13 | 而当模式中的第二个字符是`*`时: 14 | 如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式: 15 | 1、模式后移2字符,相当于x`*`被忽略; 16 | 2、字符串后移1字符,模式后移2字符; 17 | 3、字符串后移1字符,模式不变,即继续匹配字符下一位,因为`*`可以匹配多位; 18 | 19 | ```java 20 | public class Solution { 21 | public boolean match(char[] str, char[] pattern) { 22 | if (str == null || pattern == null) { 23 | return false; 24 | } 25 | int strIndex = 0; 26 | int patternIndex = 0; 27 | return matchCore(str, strIndex, pattern, patternIndex); 28 | } 29 | 30 | public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) { 31 | //有效性检验:str到尾,pattern到尾,匹配成功 32 | if (strIndex == str.length && patternIndex == pattern.length) { 33 | return true; 34 | } 35 | //pattern先到尾,匹配失败 36 | if (strIndex != str.length && patternIndex == pattern.length) { 37 | return false; 38 | } 39 | //模式第2个是*,且字符串第1个跟模式第1个匹配,分3种匹配模式;如不匹配,模式后移2位 40 | if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') { 41 | if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) { 42 | return matchCore(str, strIndex, pattern, patternIndex + 2)//模式后移2,视为x*匹配0个字符 43 | || matchCore(str, strIndex + 1, pattern, patternIndex + 2)//视为模式匹配1个字符 44 | || matchCore(str, strIndex + 1, pattern, patternIndex);//*匹配1个,再匹配str中的下一个 45 | } else { 46 | return matchCore(str, strIndex, pattern, patternIndex + 2); 47 | } 48 | } 49 | //模式第2个不是*,且字符串第1个跟模式第1个匹配,则都后移1位,否则直接返回false 50 | if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) { 51 | return matchCore(str, strIndex + 1, pattern, patternIndex + 1); 52 | } 53 | return false; 54 | } 55 | } 56 | ``` 57 | 58 | 59 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1052.md: -------------------------------------------------------------------------------- 1 | ## 表示数值的字符串 2 | 3 | **题目:** 4 | >请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"`+`100","5e2","`-`123","3.1416"和"`-`1E`-`16"都表示数值。 但是"12e","1a3.14","1.2.3","`+-`5"和"12e`+`4.3"都不是。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | ```java 11 | public class Solution { 12 | public boolean isNumeric(char[] str) { 13 | String string = String.valueOf(str); 14 | return string.matches("[\\+-]?[0-9]*(\\.[0-9]*)?([eE][\\+-]?[0-9]+)?"); 15 | } 16 | } 17 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1053.md: -------------------------------------------------------------------------------- 1 | ## 符流中第一个不重复的字符 2 | 3 | **题目:** 4 | >请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。 5 | - **输出描述:** 6 | 如果当前字符流没有存在出现一次的字符,返回`#`字符。 7 | 8 | --- 9 | 10 | ### 思路分析 11 | 12 | >一个字符占8位,因此不会超过256个,可以申请一个256大小的数组来实现一个简易的哈希表。时间复杂度为O(1),空间复杂度O(n). 13 | 14 | ```java 15 | public class Solution 16 | { 17 | int[] hashtable=new int[256]; 18 | StringBuffer s=new StringBuffer(); 19 | //Insert one char from stringstream 20 | public void Insert(char ch) 21 | { 22 | s.append(ch); 23 | if(hashtable[ch]==0) 24 | hashtable[ch]=1; 25 | else hashtable[ch]+=1; 26 | } 27 | //return the first appearence once char in current stringstream 28 | public char FirstAppearingOnce() 29 | { 30 | char[] str=s.toString().toCharArray(); 31 | for(char c:str) 32 | { 33 | if(hashtable[c]==1) 34 | return c; 35 | } 36 | return '#'; 37 | } 38 | } 39 | 40 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1054.md: -------------------------------------------------------------------------------- 1 | ## 表中环的入口结点 2 | 3 | **题目:** 4 | >一个链表中包含环,请找出该链表的环的入口结点。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | 13 |    public ListNode EntryNodeOfLoop(ListNode pHead) 14 |   { 15 |        if(pHead==null||pHead.next==null) 16 |            return null; 17 |        ListNode p1=new ListNode(0); 18 |        ListNode p2=new ListNode(0); 19 |        p1=pHead; 20 |        p2=p1; 21 |        while(p1.next!=null){ 22 |            if(p2.next==null) 23 |                return null; 24 |            p1=p1.next; 25 |            p2.next=null; 26 |            p2=p1; 27 |       } 28 |        return p2; 29 |   } 30 | } 31 | ``` 32 | 33 | 没有考虑没有环的情况,测试用例没有考虑全面 34 | 35 | ### 思路分析 36 | 37 | > *第一步*,找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。 38 | > *第二步*,找环的入口。接上步,当p1==p2时,p2所经过节点数为2x,p1所经过节点数为x,设环中有n个节点,p2比p1多走一圈有2x=n+x; n=x;可以看出p1实际走了一个环的步数,再让p2指向链表头部,p1位置不变,p1,p2每次走一步直到p1==p2; 此时p1指向环的入口。 39 | 40 | ```java 41 | public class Solution { 42 | 43 | ListNode EntryNodeOfLoop(ListNode pHead){ 44 | if(pHead == null || pHead.next == null) 45 | return null; 46 | ListNode p1 = pHead; 47 | ListNode p2 = pHead; 48 | while(p2 != null && p2.next != null ){ 49 | p1 = p1.next; 50 | p2 = p2.next.next; 51 | if(p1 == p2){ 52 | p2 = pHead; 53 | while(p1 != p2){ 54 | p1 = p1.next; 55 | p2 = p2.next; 56 | } 57 | if(p1 == p2) 58 | return p1; 59 | } 60 | } 61 | return null; 62 | } 63 | } 64 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1055.md: -------------------------------------------------------------------------------- 1 | ## 除链表中重复的结点 2 | 3 | **题目:** 4 | >在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | ```java 11 | /* 12 | public class ListNode { 13 | int val; 14 | ListNode next = null; 15 | 16 | ListNode(int val) { 17 | this.val = val; 18 | } 19 | } 20 | */ 21 | public class Solution { 22 | public ListNode deleteDuplication(ListNode pHead) 23 | { 24 | if(pHead==null) return null; 25 | ListNode pPreNode=null; 26 | ListNode pNode=pHead; 27 | while(pNode!=null){ 28 | ListNode pNext=pNode.next; 29 | boolean needDelete=false; 30 | if(pNext!=null&&pNext.val==pNode.val){ 31 | needDelete=true; 32 | } 33 | if(!needDelete){ 34 | pPreNode=pNode; 35 | pNode=pNode.next; 36 | } 37 | else{ 38 | int value=pNode.val; 39 | ListNode pToBeDel=pNode; 40 | while(pToBeDel!=null&&pToBeDel.val==value){ 41 | pNext=pToBeDel.next; 42 | pToBeDel=null; 43 | pToBeDel=pNext; 44 | } 45 | if(pPreNode==null){ 46 | pHead=pNext; 47 | } 48 | else 49 | pPreNode.next=pNext; 50 | pNode=pNext; 51 | } 52 | 53 | } 54 | return pHead; 55 | } 56 | } 57 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1056.md: -------------------------------------------------------------------------------- 1 | ## 二叉树的下一个结点 2 | 3 | **题目:** 4 | >给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子树,同时包含指向父结点的指针。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | >分析二叉树的下一个节点,一共有以下情况: 11 | 1.二叉树为空,则返回空; 12 | 2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点; 13 | 3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。 14 | 15 | ```java 16 | /* 17 | public class TreeLinkNode { 18 | int val; 19 | TreeLinkNode left = null; 20 | TreeLinkNode right = null; 21 | TreeLinkNode next = null; 22 | TreeLinkNode(int val) { 23 | this.val = val; 24 | } 25 | } 26 | */ 27 | public class Solution { 28 | public TreeLinkNode GetNext(TreeLinkNode pNode) 29 | { 30 | if(pNode==null) return null; 31 | if(pNode.right!=null){ 32 | pNode=pNode.right; 33 | while(pNode.left!=null){ 34 | pNode=pNode.left; 35 | } 36 | return pNode; 37 | } 38 | while(pNode.next!=null){ 39 | if(pNode.next.left==pNode){ 40 | return pNode.next; 41 | } 42 | pNode=pNode.next; 43 | 44 | } 45 | return null; 46 | 47 | } 48 | } 49 | ``` 50 | 51 | ```java 52 | /* 53 | public class TreeLinkNode { 54 | int val; 55 | TreeLinkNode left = null; 56 | TreeLinkNode right = null; 57 | TreeLinkNode next = null; 58 | 59 | TreeLinkNode(int val) { 60 | this.val = val; 61 | } 62 | } 63 | */ 64 | public class Solution { 65 | public TreeLinkNode GetNext(TreeLinkNode pNode) 66 | { 67 | if(pNode==null) return null; 68 | TreeLinkNode pNext=null; 69 | if(pNode.right!=null){ 70 | TreeLinkNode pRight=pNode.right; 71 | while(pRight.left!=null){ 72 | pRight=pRight.left; 73 | } 74 | pNext=pRight; 75 | } 76 | else if(pNode.next!=null){ 77 | TreeLinkNode pCurrent=pNode; 78 | TreeLinkNode pParent=pNode.next; 79 | while(pParent!=null&&pCurrent==pParent.right){ 80 | pCurrent=pParent; 81 | pParent=pParent.next; 82 | } 83 | pNext=pParent; 84 | } 85 | return pNext; 86 | } 87 | } 88 | ``` 89 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1057.md: -------------------------------------------------------------------------------- 1 | ## 对称的二叉树 2 | 3 | **题目:** 4 | >请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | >思路:首先根节点以及其左右子树,左子树的左子树和右子树的右子树相同; 11 |    左子树的右子树和右子树的左子树相同即可,采用递归非递归也可,采用栈或队列存取各级子树根节点. 12 | 13 | ```java 14 | public class Solution { 15 | boolean isSymmetrical(TreeNode pRoot) 16 | { 17 | if(pRoot == null){ 18 | return true; 19 | } 20 | return comRoot(pRoot.left, pRoot.right); 21 | } 22 | private boolean comRoot(TreeNode left, TreeNode right) { 23 | // TODO Auto-generated method stub 24 | if(left == null) return right==null; 25 | if(right == null) return false; 26 | if(left.val != right.val) return false; 27 | return comRoot(left.right, right.left) && comRoot(left.left, right.right); 28 | } 29 | } 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1058.md: -------------------------------------------------------------------------------- 1 | ## 按之字形顺序打印二叉树 2 | 3 | **题目:** 4 | >请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | >大家的实现很多都是将每层的数据存进ArrayList中,偶数层时进行reverse操作,在海量数据时,这样效率太低了。(我有一次面试,算法考的就是之字形打印二叉树,用了reverse, 11 | 直接被鄙视了,面试官说海量数据时效率根本就不行。)下面的实现:不必将每层的数据存进ArrayList中,偶数层时进行reverse操作,直接按打印顺序存入 12 | - 思路:利用Java中的LinkedList的底层实现是双向链表的特点。 13 | 1.可用做队列,实现树的层次遍历 14 | 2.可双向遍历,奇数层时从前向后遍历,偶数层时从后向前遍历. 15 | 16 | --- 17 | 18 | ```java 19 | public ArrayList > Print(TreeNode pRoot) { 20 | ArrayList> ret = new ArrayList<>(); 21 | if (pRoot == null) { 22 | return ret; 23 | } 24 | ArrayList list = new ArrayList<>(); 25 | LinkedList queue = new LinkedList<>(); 26 | queue.addLast(null);//层分隔符 27 | queue.addLast(pRoot); 28 | boolean leftToRight = true; 29 | 30 | while (queue.size() != 1) { 31 | TreeNode node = queue.removeFirst(); 32 | if (node == null) {//到达层分隔符 33 | Iterator iter = null; 34 | if (leftToRight) { 35 | iter = queue.iterator();//从前往后遍历 36 | } else { 37 | iter = queue.descendingIterator();//从后往前遍历 38 | } 39 | leftToRight = !leftToRight; 40 | while (iter.hasNext()) { 41 | TreeNode temp = (TreeNode)iter.next(); 42 | list.add(temp.val); 43 | } 44 | ret.add(new ArrayList(list)); 45 | list.clear(); 46 | queue.addLast(null);//添加层分隔符 47 | continue;//一定要continue 48 | } 49 | if (node.left != null) { 50 | queue.addLast(node.left); 51 | } 52 | if (node.right != null) { 53 | queue.addLast(node.right); 54 | } 55 | } 56 | 57 | return ret; 58 | } 59 | ``` 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1059.md: -------------------------------------------------------------------------------- 1 | ## 二叉树打印成多行 2 | 3 | **题目:** 4 | >从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。 5 | 6 | --- 7 | 8 | ### 我的代码 9 | 10 | ```java 11 | public class Solution { 12 | ArrayList > Print(TreeNode pRoot) { 13 | ArrayList> level=new ArrayList>(); 14 | if(pRoot==null) return level; 15 | LinkedList queue=new LinkedList<>(); 16 | queue.addLast(pRoot); 17 | int cur=0; 18 | int last=1; 19 | while(cur temp=new ArrayList(); 22 | while(cur请实现两个函数,分别用来序列化和反序列化二叉树 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | ```java 11 | import java.util.*; 12 | public class Solution { 13 | String Serialize(TreeNode root) { 14 | if(root == null) 15 | { 16 | return "#,"; 17 | } 18 | String res = root.val + ","; 19 | res += Serialize(root.left); 20 | res += Serialize(root.right); 21 | return res; 22 | } 23 | TreeNode Deserialize(String str) { 24 | String[] values = str.split(","); 25 | Queue queue= new LinkedList(); 26 | for(int i = 0;i != values.length; i ++) 27 | { 28 | queue.offer(values[i]); 29 | } 30 | return preOrder(queue); 31 | } 32 | public TreeNode preOrder(Queue queue) 33 | { 34 | String value = queue.poll(); 35 | if(value.equals("#")) 36 | { 37 | return null; 38 | } 39 | TreeNode head = new TreeNode(Integer.valueOf(value)); 40 | head.left = preOrder(queue); 41 | head.right = preOrder(queue); 42 | return head; 43 | } 44 | } 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1061.md: -------------------------------------------------------------------------------- 1 | ## 二叉搜索树的第k个结点 2 | 3 | **题目:** 4 | >给定一颗二叉搜索树,请找出其中的第k小的结点。例如, 5 | ``` 6 | 5 7 | / \ 8 | 3 7 9 | / \ / \ 10 | 2 4 6 8 11 | ``` 12 | 中,按结点数值大小顺序第三个结点的值为4。 13 | 14 | --- 15 | 16 | ### 思路分析 17 | 18 | ```java 19 | import java.util.Stack; 20 | public class Solution { 21 | //中序递归 22 | int count = 0; 23 | TreeNode KthNode(TreeNode pRoot, int k) 24 | { 25 | if(count > k || pRoot == null) 26 | return null; 27 | TreeNode p = pRoot; 28 | Stack LDRStack = new Stack(); 29 | TreeNode kthNode = null; 30 | while(p != null || !LDRStack.isEmpty()){ 31 | while(p != null){ 32 | LDRStack.push(p); 33 | p = p.left; 34 | } 35 | TreeNode node = LDRStack.pop(); 36 | System.out.print(node.val+","); 37 | count++; 38 | if(count == k){ 39 | kthNode = node; 40 | } 41 | p = node.right; 42 | } 43 | return kthNode; 44 | } 45 | } 46 | ``` 47 | 48 | 49 | ```java 50 | /* 51 | public class TreeNode { 52 | int val = 0; 53 | TreeNode left = null; 54 | TreeNode right = null; 55 | 56 | public TreeNode(int val) { 57 | this.val = val; 58 | 59 | } 60 | 61 | } 62 | */ 63 | public class Solution { 64 | TreeNode KthNode(TreeNode pRoot, int k) 65 | { 66 | if(pRoot==null||k==0) return null; 67 | return KthNodeCore(pRoot,k); 68 | } 69 | TreeNode KthNodeCore(TreeNode pRoot,int k){ 70 | TreeNode target=null; 71 | if(pRoot.left!=null) 72 | target=KthNodeCore(pRoot.left,k); 73 | if(target==null){ 74 | if(k==1){ 75 | target=pRoot; 76 | } 77 | k--; 78 | } 79 | if(target==null&&pRoot.right!=null) 80 | target=KthNodeCore(pRoot.right,k); 81 | return target; 82 | } 83 | } 84 | ``` 85 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1062.md: -------------------------------------------------------------------------------- 1 | ## 据流中的中位数 2 | 3 | **题目:** 4 | >如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | >用最大堆和最小堆、AVL树、排序链表。 11 | 12 | ```java 13 | import java.util.*; 14 | public class Solution { 15 | ArrayList al = new ArrayList(); 16 | public void Insert(Integer num) { 17 | al.add(num); 18 | Collections.sort(al); 19 | } 20 | public Double GetMedian() { 21 | int mid = al.size()/2; 22 | if((al.size()&1) == 0){ 23 | Integer n1 = al.get(mid); 24 | Integer n2 = al.get(mid - 1); 25 | double s = (Double.valueOf(n1 + "") + Double.valueOf(n2 + ""))/2; 26 | return s; 27 | }else{ 28 | double s = Double.valueOf(al.get(mid) + ""); 29 | return s; 30 | } 31 | } 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1063.md: -------------------------------------------------------------------------------- 1 | ## 动窗口的最大值 2 | 3 | **题目:** 4 | >给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | 实际上一个窗口可以看成一个队列。当窗口滑动时,处于窗口的第一个数字被删除,同时在窗口的末尾添加一个新的数字。这符合队列的先进先出特性。如果能从队列中找出它的最大数,这个问题就解决了。 11 | 12 | 13 | ```java 14 | import java.util.*; 15 | /** 16 | 用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次 17 | 1.判断当前最大值是否过期 18 | 2.新增加的值从队尾开始比较,把所有比他小的值丢掉 19 | */ 20 | public class Solution { 21 | public ArrayList maxInWindows(int [] num, int size) 22 | { 23 | ArrayList res = new ArrayList<>(); 24 | if(size == 0) return res; 25 | int begin; 26 | ArrayDeque q = new ArrayDeque<>(); 27 | for(int i = 0; i < num.length; i++){ 28 | begin = i - size + 1; 29 | if(q.isEmpty()) 30 | q.add(i); 31 | else if(begin > q.peekFirst()) 32 | q.pollFirst(); 33 | 34 | while((!q.isEmpty()) && num[q.peekLast()] <= num[i]) 35 | q.pollLast(); 36 | q.add(i); 37 | if(begin >= 0) 38 | res.add(num[q.peekFirst()]); 39 | } 40 | return res; 41 | } 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1064.md: -------------------------------------------------------------------------------- 1 | ## 矩阵中的路径 2 | 3 | **题目:** 4 | >请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。 5 | 6 | --- 7 | 8 | ### 思路分析 9 | 10 | 这是一个可以用回溯法的典型题。首先,在矩阵中任先一个格子作为路径的起点。假设矩阵中某个格子的字符为ch并且这个格子将对应于路径上的第i个字符。如果路径上的第i个字符正好是ch,那么往相邻的格子寻找路径上的第i+1个字符。除在矩阵边界上的格子之外,其他格子都有4个相邻的格子。路径可以看成是一个栈。当在举证中定位了路径中前n个字符的位置之后,在与第n个字符对应的格子的周围都没有找到第n+1个字符,这个时候只好在路径上回到第n-1个字符,重新定位第n个字符。 11 | 12 | ```java 13 | //用一个状态数组保存之前访问过的字符,然后再分别按上,下,左,右递归 14 | 15 | public class Solution { 16 | public boolean hasPath(char[] matrix, int rows, int cols, char[] str) { 17 | int flag[] = new int[matrix.length]; 18 | for (int i = 0; i < rows; i++) { 19 | for (int j = 0; j < cols; j++) { 20 | if (helper(matrix, rows, cols, i, j, str, 0, flag)) 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | private boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) { 27 | int index = i * cols + j; 28 | if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1) 29 | return false; 30 | if(k == str.length - 1) return true; 31 | flag[index] = 1; 32 | if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag) 33 | || helper(matrix, rows, cols, i + 1, j, str, k + 1, flag) 34 | || helper(matrix, rows, cols, i, j - 1, str, k + 1, flag) 35 | || helper(matrix, rows, cols, i, j + 1, str, k + 1, flag){ 36 | return true; 37 | } 38 | flag[index] = 0; 39 | return false; 40 | } 41 | } 42 | ``` -------------------------------------------------------------------------------- /JianZhiOffer/Code/Q1065.md: -------------------------------------------------------------------------------- 1 | ## 机器人的运动范围 2 | 3 | **题目:** 4 | >地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子? 5 | 6 | --- 7 | ### 思路分析 8 | 9 | 回溯法 10 | 11 | ```java 12 | public class Solution { 13 | public int movingCount(int threshold, int rows, int cols) { 14 | int flag[][] = new int[rows][cols]; //记录是否已经走过 15 | return helper(0, 0, rows, cols, flag, threshold); 16 | } 17 | 18 | private int helper(int i, int j, int rows, int cols, int[][] flag, int threshold) { 19 | if (i < 0 || i >= rows || j < 0 || j >= cols || numSum(i) + numSum(j) > threshold || flag[i][j] == 1) return 0; 20 | flag[i][j] = 1; 21 | return helper(i - 1, j, rows, cols, flag, threshold) 22 | + helper(i + 1, j, rows, cols, flag, threshold) 23 | + helper(i, j - 1, rows, cols, flag, threshold) 24 | + helper(i, j + 1, rows, cols, flag, threshold) 25 | + 1; 26 | } 27 | private int numSum(int i) { 28 | int sum = 0; 29 | do{ 30 | sum += i%10; 31 | }while((i = i/10) > 0); 32 | return sum; 33 | } 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1014P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1014P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1015P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1015P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1016P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1016P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1017P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1017P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1018P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1018P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1020P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1020P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1021P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1021P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1023P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1023P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1024P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1024P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1024P2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1024P2.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1024P3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1024P3.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1025P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1025P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1026P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1026P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1027P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1027P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1027P2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1027P2.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1028P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1028P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1029P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1029P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1029P2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1029P2.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1029P3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1029P3.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1030P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1030P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1033P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1033P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1033P2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1033P2.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1034P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1034P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1035P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1035P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1036P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1036P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1037P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1037P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1038P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1038P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1039P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1039P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1040P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1040P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1041P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1041P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1041P2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1041P2.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1042P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1042P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1043P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1043P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1044P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1044P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1045P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1045P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1045P2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1045P2.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1045P3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1045P3.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1047P1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1047P1.png -------------------------------------------------------------------------------- /JianZhiOffer/Code/pic/Q1047P2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyricYang/Internet-Recruiting-Algorithm-Problems/ce2b56247a6f367174026771903442551a10adf4/JianZhiOffer/Code/pic/Q1047P2.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Lyric 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # 程序员面试笔试算法题 2 | 3 | [^_^]: 4 | ![license](https://img.shields.io/github/license/mashape/apistatus.svg) 5 | 6 | [![](https://img.shields.io/github/followers/lyricyang.svg?style=social&label=Follow%20Me)](https://github.com/LyricYang) 7 | 8 | 面试造火箭,工作拧螺丝!作为一名程序猿,必须有造火箭的本事,才能有拧螺丝的机会,其中数据结构和算法是一项必须掌握和灵活运用的技能。为了温故而知新,我根据题源将题目分类如下,主要包括17和18年招聘时各公司的笔试题、《程序员代码面试指南》、面试过程中的算法题等,语言选择的是**JAVA**,题库会慢慢完善。 9 | 10 | 欢迎star,希望对大伙有用。 11 | 12 | ## 公司招聘算法笔试题解答 13 | 14 | 各大互联网公司近两年招聘的算法编程题,只总结了部分,后续会不断补充。题解代码只是个人的思路,并不是最优的,有些题有解题说明,便于自己回忆和理解代码。 15 | 16 | 附上链接:[公司招聘算法笔试题解答](https://github.com/LyricYang/Internet-Recruiting-Algorithm-Problems/blob/master/InternetRecruitingAlgorithmProblems/Readme.md) 17 | 18 | ## 《程序员代码面试指南》源码分章总结 19 | 20 | 这本书不仅可以作为代码面试指南,还可以作为学生与程序员的辅助练习。作者刷题5年,悉数总结都沉淀在这本书里,相信跟着他的引导,从头到尾逐一攻克一定会有所收获。 21 |   ——叶向宇牛客网CEO 22 | 23 | 附上链接:[程序员代码面试指南](https://github.com/LyricYang/Internet-Recruiting-Algorithm-Problems/blob/master/CodeInterviewGuide/README.md) 24 | 25 | ## 《剑指offer》 26 | 27 | 《剑指offer》中的题目在笔试面试中经常遇到,可以在[牛客网](https://www.nowcoder.com/ta/coding-interviews)上在线编程。我在总结时,会给出自己的代码(自己做题时的思路)和书中的参考代码,代码还是以书上的为准。 28 | 29 | 附上链接:[剑指Offer](https://github.com/LyricYang/Internet-Recruiting-Algorithm-Problems/blob/master/JianZhiOffer/README.md) 30 | 31 | ## 面试过程中遇到的手写代码题 32 | 33 | 面试过程中面试官往往会让你针对实际问题手写代码或者提出几个问题让你描述解题思路,写出关键代码。 34 | 35 | 附上链接:[面试中手撕的代码问题](https://github.com/LyricYang/Internet-Recruiting-Algorithm-Problems/blob/master/INTERVIEW/Interview.md) 36 | 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------