├── .gitignore ├── readme.md └── src ├── base ├── BFSDemo.java ├── DFSDemo.java ├── HeapTest.java ├── greedy │ ├── 做项目获得最大钱数.java │ ├── 字符串数组拼接.java │ ├── 最多宣讲场次.java │ └── 最小代价.java ├── prefixtree │ └── TrieTree.java ├── recursiveANDdynamic │ ├── 二维数组最小路径和.java │ ├── 字符串全排列.java │ ├── 字符串全部子序列.java │ ├── 数组累加和.java │ ├── 母牛的数量.java │ ├── 求n的阶乘.java │ └── 汉诺塔问题.java ├── sort │ ├── _01BubbleSort.java │ ├── _02SelectionSort.java │ ├── _03InsertionSort.java │ ├── _04MergeSort.java │ ├── _05QuickSort.java │ ├── _06HeapSort.java │ └── _07ShellSort.java └── unionfind │ └── 岛问题.java ├── ctci ├── _11_9AntiOrder.java ├── _1_1Different.java ├── _1_2Reverse.java ├── _1_3Same.java ├── _1_4replaceSpace.java ├── _1_5Zipper.java ├── _1_6Transform.java ├── _1_7Clearer.java ├── _1_8ReverseEqual.java ├── _2_2FindKthToTail.java ├── _2_3removeNode.java ├── _2_4Partition.java ├── _2_5Plus.java ├── _2_5Plus_2.java ├── _2_7Palindrome.java ├── _3_3SetOfStacks.java ├── _3_5stackQueue.java ├── _3_6twoStacksSort.java ├── _3_7CatDogAsylum.java ├── _4_1Balance.java ├── _4_1Balance_2.java ├── _4_2Path.java ├── _4_3buildMinimalBST.java ├── _4_4TreeLevel.java ├── _4_5checkBST.java ├── _4_6Successor.java ├── _4_6Successor_2.java ├── _4_7LCA.java ├── _4_9FindPath.java ├── _4_9FindPath_2.java ├── _5_1BinInsert.java ├── _5_2BinDecimal.java ├── _5_3CloseNumber.java ├── _5_5Transform.java ├── _5_6Exchange.java ├── _5_7Finder.java ├── _5_8Render.java ├── _7_7KthNumber.java ├── _9_1GoUpstairs.java ├── _9_2_1Robot.java ├── _9_2_2Robot.java ├── _9_3_1MagicIndex.java ├── _9_3_2MagicIndex.java ├── _9_4Subset.java ├── _9_4Subset_2.java ├── _9_5Permutation.java ├── _9_6Parenthesis.java ├── _9_7Flood.java └── _9_8Coins.java ├── leetcode └── easy │ ├── _1TwoSum.java │ ├── _7ReverseInteger.java │ └── _9PalindromeNumber.java ├── offer ├── _03SearchIn2dArray.java ├── _04ReplaceAllSpace.java ├── _05PrintListTailToHead_1.java ├── _05PrintListTailToHead_2.java ├── _06ReConstructBinaryTree.java ├── _07StackImplementsQueue.java ├── _08MinNumberInRotatedArray.java ├── _08MinNumberInRotatedArray_2.java ├── _09Fibonacci.java ├── _09Fibonacci_2.java ├── _09JumpFloor.java ├── _09JumpFloorII.java ├── _09RectCover.java ├── _10NumberOf1.java ├── _11Power.java ├── _11Power_2.java ├── _14reOrderArray.java ├── _15FindKthToTail.java ├── _16ReverseList.java ├── _17Merge.java ├── _17Merge_2.java ├── _18HasSubtree.java ├── _19Mirror.java ├── _20printMatrix.java ├── _20printMatrix_2.java ├── _21stack.java ├── _22IsPopOrder.java ├── _23PrintFromTopToBottom.java ├── _24VerifySquenceOfBST.java ├── _25FindPath.java ├── _25FindPath_2.java ├── _26RandomListNode.java ├── _26RandomListNode_2.java ├── _27Convert.java ├── _28Permutation.java ├── _29MoreThanHalfNum_Solution.java ├── _29MoreThanHalfNum_Solution_2.java ├── _29MoreThanHalfNum_Solution_3.java ├── _30GetLeastNumbers_Solution.java ├── _30GetLeastNumbers_Solution_2.java ├── _30GetLeastNumbers_Solution_3.java ├── _30GetLeastNumbers_Solution_4.java ├── _31FindGreatestSumOfSubArray.java ├── _32NumberOf1Between1AndN.java ├── _33PrintMinNumber.java ├── _34GetUglyNumber.java ├── _35FirstNotRepeatingChar.java ├── _36InversePairs.java ├── _37FindFirstCommonNode.java ├── _37FindFirstCommonNode_2.java ├── _38GetNumberOfK.java ├── _39IsBalanced.java ├── _39IsBalanced_2.java ├── _39TreeDepth.java ├── _40FindNumsAppearOnce.java ├── _40FindNumsAppearOnce_2.java ├── _41FindContinuousSequence.java ├── _41FindNumbersWithSum.java ├── _42LeftRotateString.java ├── _42ReverseSentence.java ├── _44isContinuous.java ├── _45LastRemaining.java ├── _46Sum.java ├── _47Add.java ├── _49StrToInt.java ├── _50duplicate.java ├── _51multiply.java ├── _52match.java ├── _53isNumeric.java ├── _54FirstAppearingOnce.java ├── _55EntryNodeOfLoop.java ├── _56deleteDuplication.java ├── _57GetNext.java ├── _58isSymmetrical.java ├── _59Print.java ├── _60Print.java ├── _61Serialize.java ├── _62KthNode.java ├── _63GetMedian.java ├── _64maxInWindows.java ├── _65hasPath.java └── _66movingCount.java └── simulation ├── 判断字符串由子串复制组成.java ├── 因式分解.java ├── 括号配对所有情况.java ├── 整数划分最大乘积.java ├── 最多硬币问题.java ├── 最小不能表示的数.java ├── 歌单组成方式.java ├── 符合条件的子串.java ├── 翻转数列.java └── 镜像回文.java /.gitignore: -------------------------------------------------------------------------------- 1 | out/* 2 | .idea/* 3 | nowcoder.iml 4 | review.txt 5 | src/test/* 6 | -------------------------------------------------------------------------------- /src/base/DFSDemo.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | //地图场景中的深度优先搜索(穷举):朝一个方向一直走,走不通换方向,然后返回,擦除标记,寻找其他路径 4 | /* 5 | s 0 0 0 0 6 | 0 0 1 1 0 7 | 0 0 1 e 0 8 | 0 0 0 0 0 9 | 0 0 0 0 0 10 | 11 | s起点,e终点,1障碍物 12 | */ 13 | public class DFSDemo { 14 | //设定x,y轴最大值,创建地图 15 | static int max_x = 100; 16 | static int max_y = 100; 17 | static int[][] map = new int[max_x][max_y]; 18 | //设定方向 19 | static int[][] next = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; 20 | //标记是否走过 21 | static boolean[][] mark = new boolean[max_x][max_y]; 22 | //最少步数 23 | static int min_step = Integer.MAX_VALUE; 24 | 25 | public static void main(String[] args) { 26 | map[3][2] = 100;//设置目的地e的值 27 | map[3][1] = 1;//障碍物 28 | map[2][2] = 1; 29 | map[4][2] = 1; 30 | 31 | //深度优先搜索 32 | dfs(0, 0, 1); 33 | 34 | System.out.println(min_step); 35 | 36 | } 37 | 38 | 39 | private static void dfs(int x, int y, int step) { 40 | //判断条件:若到达目的地 或 步数大于现有最小值 或 步数大于容忍的值(防止溢出) 41 | if (map[x][y] == 100 || step > min_step || step > 20) { 42 | min_step = Math.min(step, min_step); 43 | return; 44 | } 45 | //若没到,走一步 46 | for (int i = 0; i < next.length; i++) { 47 | int next_x = x + next[i][0]; //i=0 时往右走一步; 48 | int next_y = y + next[i][1]; 49 | //判断边界,走不通了,走过了,碰到障碍物了。则直接执行下一次循环,即换一个方向走 50 | if (next_x == max_x || next_y == max_y || next_x == -1 || next_y == -1 51 | || mark[next_x][next_y] || map[next_x][next_y] == 1) 52 | continue; 53 | //标记已经走过的点 54 | mark[next_x][next_y] = true; 55 | dfs(next_x, next_y, step + 1); //这里使用递归,当i=0时实现一直往右走,其他类推 56 | mark[next_x][next_y] = false;//擦除这个点的记录,回过头来找其他的路 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/base/HeapTest.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.util.Comparator; 4 | import java.util.PriorityQueue; 5 | 6 | //测试jdk中二叉堆的插入数据和删除数据的过程(基于最大堆) 7 | public class HeapTest { 8 | public PriorityQueue getQueue(int[] input) { 9 | PriorityQueue maxHeap = new PriorityQueue<>(new Comparator() { 10 | @Override 11 | public int compare(Integer o1, Integer o2) { 12 | return o2.compareTo(o1); //最大的放前面 13 | } 14 | }); 15 | for (int i = 0; i < input.length; i++) { 16 | maxHeap.offer(input[i]); 17 | } 18 | //maxHeap.poll(); 19 | //maxHeap.poll(); 20 | //maxHeap.poll(); 21 | //maxHeap.poll(); 22 | return maxHeap; 23 | } 24 | 25 | 26 | public static void main(String[] args) { 27 | int[] input = {4, 5, 1, 6, 2, 7, 3, 8}; 28 | HeapTest instance = new HeapTest(); 29 | PriorityQueue queue = instance.getQueue(input); 30 | System.out.println(queue); 31 | } 32 | } 33 | 34 | /** 35 | * 总结:(以最大堆举例) 36 | * 二叉堆除了最底层外,是完全充满的,从左往右填充 37 | * 当插入数据时,先插在最后面,然后与上一层数据相比,如果比他大则互换,直到不能换为止 38 | * 当删除数据时,删除根节点上的值,然后用最后一个值赋值给根节点,下一层的比根节点大的值和他互换,依次下沉 39 | */ 40 | -------------------------------------------------------------------------------- /src/base/greedy/字符串数组拼接.java: -------------------------------------------------------------------------------- 1 | package base.greedy; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | /* 7 | 字符串拼接,找到字典序最小的结果 8 | */ 9 | public class 字符串数组拼接 { 10 | public static class MyComparator implements Comparator { 11 | 12 | @Override 13 | public int compare(String s1, String s2) { 14 | return (s1 + s2).compareTo(s2 + s1); 15 | } 16 | } 17 | 18 | private static String lowestString(String[] strs) { 19 | if (strs == null || strs.length == 0) return ""; 20 | Arrays.sort(strs, new MyComparator()); 21 | StringBuilder sb = new StringBuilder(); 22 | for (String s : strs) { 23 | sb.append(s); 24 | } 25 | return sb.toString(); 26 | } 27 | 28 | public static void main(String[] args) { 29 | String[] strs1 = {"jibw", "ji", "jp", "bw", "jibw"}; 30 | System.out.println(lowestString(strs1)); 31 | 32 | String[] strs2 = {"ba", "b"}; 33 | System.out.println(lowestString(strs2)); 34 | 35 | } 36 | 37 | 38 | } 39 | 40 | 41 | /* 42 | 贪心策略:str1.str2 <= str2.str1?str1放前:str2放前 43 | 44 | 比较器设置需要有传递性: 45 | a.b <= b.a 46 | b.c <= c.b 47 | 推出 48 | a.c <= c.a 49 | */ -------------------------------------------------------------------------------- /src/base/greedy/最多宣讲场次.java: -------------------------------------------------------------------------------- 1 | package base.greedy; 2 | 3 | import java.util.Comparator; 4 | import java.util.PriorityQueue; 5 | import java.util.Scanner; 6 | 7 | /* 8 | 一些项目要占用一个会议室宣讲, 会议室不能同时容纳两个项目 9 | 的宣讲。 给你每一个项目开始的时间和结束的时间(给你一个数 10 | 组, 里面 是一个个具体的项目), 你来安排宣讲的日程, 要求会 11 | 议室进行的宣讲的场次最多。 返回这个最多的宣讲场次。 12 | 输入: 13 | 第一行: 总项目数 14 | 第二行: 每个项目开始时间 15 | 第三行: 每个项目结束时间 16 | 输出: 17 | 最多场次数 18 | */ 19 | public class 最多宣讲场次 { 20 | public static class Pro { 21 | int s; 22 | int e; 23 | 24 | public Pro(int s, int e) { 25 | this.s = s; 26 | this.e = e; 27 | } 28 | } 29 | 30 | 31 | private static int findMaxNum(int n, int[] start, int[] end) { 32 | PriorityQueue minHeap = new PriorityQueue<>(new Comparator() { 33 | @Override 34 | public int compare(Pro o1, Pro o2) { 35 | return o1.e - o2.e; 36 | } 37 | }); 38 | for (int i = 0; i < n; i++) 39 | minHeap.add(new Pro(start[i], end[i])); 40 | 41 | int res = 0; 42 | int e = 0; 43 | while (!minHeap.isEmpty()) { 44 | Pro cur = minHeap.poll(); 45 | if (cur.s >= e) { 46 | res++; 47 | e = cur.e; 48 | } 49 | } 50 | return res; 51 | } 52 | 53 | public static void main(String[] args) { 54 | Scanner sc = new Scanner(System.in); 55 | int n = sc.nextInt(); 56 | int[] start = new int[n]; 57 | int[] end = new int[n]; 58 | for (int i = 0; i < n; i++) 59 | start[i] = sc.nextInt(); 60 | for (int i = 0; i < n; i++) 61 | end[i] = sc.nextInt(); 62 | int max = findMaxNum(n, start, end); 63 | System.out.println(max); 64 | 65 | } 66 | 67 | 68 | } 69 | 70 | 71 | 72 | 73 | 74 | /* 75 | 贪心策略:优先安排结束时间早的场次 76 | 最小堆或者直接排序 77 | */ -------------------------------------------------------------------------------- /src/base/greedy/最小代价.java: -------------------------------------------------------------------------------- 1 | package base.greedy; 2 | 3 | import java.util.PriorityQueue; 4 | import java.util.Scanner; 5 | 6 | /* 7 | 一块金条切成两半, 是需要花费和长度数值一样的铜板的。 比如 8 | 长度为20的 金条, 不管切成长度多大的两半, 都要花费20个铜 9 | 板。 一群人想整分整块金条,怎么分最省铜板? 10 | 例如,给定数组{10,20,30}, 代表一共三个人, 整块金条长度为 11 | 10+20+30=60. 金条要分成10,20,30三个部分。 如果, 先把长 12 | 度60的金条分成10和50, 花费60 再把长度50的金条分成20和30, 13 | 花费50 一共花费110铜板。 14 | 但是如果, 先把长度60的金条分成30和30, 花费60 再把长度30 15 | 金条分成10和20, 花费30 一共花费90铜板。 16 | 输入一个数组, 返回分割的最小代价。 17 | */ 18 | public class 最小代价 { 19 | public static int lessMoney(int[] array) { 20 | PriorityQueue pQue = new PriorityQueue();//默认自然顺序,最小堆 21 | for (int a : array) 22 | pQue.add(a); 23 | int money = 0; 24 | int cur = 0; 25 | while (pQue.size() > 1) { 26 | cur = pQue.poll() + pQue.poll(); 27 | money += cur; 28 | pQue.add(cur); 29 | } 30 | return money; 31 | } 32 | 33 | 34 | public static void main(String[] args) { 35 | Scanner sc = new Scanner(System.in); 36 | int n = sc.nextInt(); 37 | int[] a = new int[n]; 38 | for (int i = 0; i < n; i++) 39 | a[i] = sc.nextInt(); 40 | System.out.println(lessMoney(a)); 41 | } 42 | } 43 | 44 | 45 | /* 46 | greedy+最小堆(优先队列) 47 | 哈夫曼编码 逆向思维 48 | */ -------------------------------------------------------------------------------- /src/base/prefixtree/TrieTree.java: -------------------------------------------------------------------------------- 1 | package base.prefixtree; 2 | 3 | public class TrieTree { 4 | } 5 | 6 | /* 7 | 前缀树:建一棵树,路径上是字母,从头节点开始,依次看有没有路,若有复用,若没有建出来 8 | 节点上加上数据项,是以某个字符串结尾,加了几次 9 | 再开个数据项,滑过几次,几个字符串以这作为前缀的 10 | */ -------------------------------------------------------------------------------- /src/base/recursiveANDdynamic/二维数组最小路径和.java: -------------------------------------------------------------------------------- 1 | package base.recursiveANDdynamic; 2 | 3 | /* 4 | 二维数组,每个数都是正数,左上走到右下,每一步只能向右或向下,沿途数字加起来,返回最小路径和 5 | */ 6 | public class 二维数组最小路径和 { 7 | 8 | //往右或往下的最短路径 暴力递归枚举,很多重复计算,时间复杂度很高 9 | public static int walk(int[][] matrix, int i, int j) { 10 | if (i == matrix.length - 1 && j == matrix[0].length - 1) 11 | return matrix[i][j]; 12 | if (i == matrix.length - 1) 13 | return matrix[i][j] + walk(matrix, i, j + 1); 14 | if (j == matrix[0].length - 1) 15 | return matrix[i][j] + walk(matrix, i + 1, j); 16 | int right = walk(matrix, i, j + 1); 17 | int down = walk(matrix, i + 1, j); 18 | return matrix[i][j] + Math.min(right, down); 19 | } 20 | 21 | 22 | //无后效性问题(i,j确定时,返回值一定是固定的) 可改成动态规划 存到表里(右下角存放最终结果),中间结果不需要重复计算 23 | public static int walk_2(int[][] m) { 24 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 25 | return 0; 26 | } 27 | int row = m.length; 28 | int col = m[0].length; 29 | int[][] dp = new int[row][col];//创建一个存放结果的数组 30 | dp[0][0] = m[0][0]; 31 | //先定义左上的边界值 32 | for (int i = 1; i < row; i++) { 33 | dp[i][0] = dp[i - 1][0] + m[i][0]; 34 | } 35 | for (int j = 1; j < col; j++) { 36 | dp[0][j] = dp[0][j - 1] + m[0][j]; 37 | } 38 | for (int i = 1; i < row; i++) { 39 | for (int j = 1; j < col; j++) { 40 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + m[i][j]; 41 | } 42 | } 43 | return dp[row - 1][col - 1]; 44 | } 45 | 46 | public static void main(String[] args) { 47 | int[][] m = { 48 | {1, 1, 1}, 49 | {0, 0, 1}, 50 | {1, 0, 1} 51 | }; 52 | //System.out.println(walk(m, 0, 0)); 53 | System.out.println(walk_2(m)); 54 | } 55 | } 56 | 57 | /* 58 | 当前位置 + 往右或往下的最短路径 59 | 60 | 61 | 递归 ---> 动态规划 62 | */ -------------------------------------------------------------------------------- /src/base/recursiveANDdynamic/字符串全排列.java: -------------------------------------------------------------------------------- 1 | package base.recursiveANDdynamic; 2 | 3 | import java.util.Scanner; 4 | import java.util.TreeSet; 5 | 6 | /* 7 | 打印一个字符串的全排列,(要求不要出现重复的序列) 8 | */ 9 | public class 字符串全排列 { 10 | public static TreeSet set = new TreeSet<>(); 11 | 12 | private static void printAllPermutations(char[] chars, int i) { 13 | if (i == chars.length) { 14 | String s = String.valueOf(chars); 15 | if (!set.contains(s)) 16 | set.add(s); 17 | } 18 | for (int j = i; j < chars.length; j++) { 19 | swap(chars, i, j); 20 | printAllPermutations(chars, i + 1); 21 | swap(chars, j, i);//回溯 22 | } 23 | } 24 | 25 | private static void swap(char[] chars, int i, int j) { 26 | char temp = chars[i]; 27 | chars[i] = chars[j]; 28 | chars[j] = temp; 29 | } 30 | 31 | public static void main(String[] args) { 32 | Scanner sc = new Scanner(System.in); 33 | String str = sc.nextLine(); 34 | printAllPermutations(str.toCharArray(), 0); 35 | for (String s : set) { 36 | System.out.println(s); 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/base/recursiveANDdynamic/字符串全部子序列.java: -------------------------------------------------------------------------------- 1 | package base.recursiveANDdynamic; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 打印字符串的全部子序列,包括空字符串 7 | */ 8 | public class 字符串全部子序列 { 9 | 10 | public static void printAllSub(char[] chars, int i, String res) { 11 | if (i == chars.length) { 12 | System.out.println(res); 13 | return; 14 | } 15 | printAllSub(chars, i + 1, res); 16 | printAllSub(chars, i + 1, res + String.valueOf(chars[i])); 17 | } 18 | 19 | public static void main(String[] args) { 20 | Scanner sc = new Scanner(System.in); 21 | String s = sc.nextLine(); 22 | printAllSub(s.toCharArray(), 0, ""); 23 | } 24 | } 25 | 26 | /* 27 | abc 28 | 第一个位置要不要a; 第二个位置要不要b;第三个位置要不要c 打印叶子节点 29 | TrieTree "" 30 | ab TrieTree b "" 31 | abc ab ac TrieTree bc b c "" 32 | */ 33 | -------------------------------------------------------------------------------- /src/base/recursiveANDdynamic/数组累加和.java: -------------------------------------------------------------------------------- 1 | package base.recursiveANDdynamic; 2 | 3 | /* 4 | 一个数组arr都是正数,一个整数aim,如果可以任意选择arr中的数字,能不能累加得到aim,返回true或false 5 | 6 | 若有负数,sum的范围确定,加个飘逸量offset 7 | */ 8 | public class 数组累加和 { 9 | 10 | public static boolean isSum(int i, int[] arr, int sum, int aim) { //sum是当前累加和 11 | //base case 12 | if (i == arr.length) { 13 | return sum == aim; 14 | } 15 | return isSum(i + 1, arr, sum, aim) || 16 | isSum(i + 1, arr, sum + arr[i], aim); 17 | 18 | } 19 | 20 | //动态规划表 21 | public static boolean isSum_2(int[] arr, int aim) { 22 | boolean[][] dp = new boolean[arr.length + 1][aim + 1]; 23 | for (int i = 0; i < dp.length; i++) 24 | dp[i][aim] = true; //这一列全设为true 25 | for (int i = arr.length - 1; i >= 0; i--) { 26 | for (int j = aim - 1; j >= 0; j--) { 27 | if (j + arr[i] <= aim) 28 | dp[i][j] = dp[i + 1][j] || dp[i + 1][j + arr[i]]; 29 | } 30 | } 31 | return dp[0][0]; 32 | } 33 | 34 | public static void main(String[] args) { 35 | int[] arr = {2, 3, 8, 9}; 36 | //boolean b = isSum(0, arr, 0, 15); 37 | boolean b = isSum_2(arr, 19); 38 | System.out.println(b); 39 | } 40 | } 41 | 42 | 43 | /* 44 | 每个数字要或不要,叶节点是所有的决定 45 | f(0,0) 第一个0是当前下标,第二个0是当前和 46 | 47 | 转换为动态规划: 48 | 49 | 举例f(3,5)无后效性 i,sum是可变参数 50 | */ -------------------------------------------------------------------------------- /src/base/recursiveANDdynamic/母牛的数量.java: -------------------------------------------------------------------------------- 1 | package base.recursiveANDdynamic; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 母牛每年生一只母牛,新出生的母牛成长三年后也能每年生一只母牛,假设不会死。求N年后,母牛的数量 7 | */ 8 | public class 母牛的数量 { 9 | 10 | private static long getCowsNum(int n) { 11 | if (n < 1) return 0; 12 | if (n == 1 || n == 2 || n == 3) return n; 13 | return getCowsNum(n - 1) + getCowsNum(n - 3); 14 | } 15 | 16 | public static void main(String[] args) { 17 | Scanner sc = new Scanner(System.in); 18 | int n = sc.nextInt(); 19 | System.out.println(getCowsNum(n)); 20 | } 21 | 22 | } 23 | 24 | /* 25 | f(n) = f(n-1) + f(n-3) 26 | 数量 前一年的数量 新生的数量 27 | 时间复杂度 O(n) 存在一个矩阵乘法的方法O(logn) 28 | */ -------------------------------------------------------------------------------- /src/base/recursiveANDdynamic/求n的阶乘.java: -------------------------------------------------------------------------------- 1 | package base.recursiveANDdynamic; 2 | 3 | import java.util.Scanner; 4 | 5 | public class 求n的阶乘 { 6 | 7 | public static long getFactorial(int n) { 8 | //退出递归条件 base case 9 | if (n == 1) return 1L; 10 | 11 | return (long) n * getFactorial(n - 1); 12 | } 13 | 14 | public static void main(String[] args) { 15 | Scanner sc = new Scanner(System.in); 16 | int n = sc.nextInt(); 17 | System.out.println(getFactorial(n)); 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/base/recursiveANDdynamic/汉诺塔问题.java: -------------------------------------------------------------------------------- 1 | package base.recursiveANDdynamic; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 总共3个柱子,n个盘子,从第一个柱子移动到第三个柱子上;移动的过程中,不能大压小 7 | */ 8 | public class 汉诺塔问题 { 9 | 10 | public static void process(int n, String from, String to, String help) { 11 | if (n == 1) System.out.println("move " + 1 + " from " + from + " to " + to); 12 | else { 13 | process(n - 1, from, help, to); 14 | System.out.println("move " + n + " from " + from + " to " + to); 15 | process(n - 1, help, to, from); 16 | } 17 | } 18 | 19 | 20 | public static void main(String[] args) { 21 | Scanner sc = new Scanner(System.in); 22 | int n = sc.nextInt(); 23 | process(n, "左", "右", "中"); 24 | } 25 | } 26 | 27 | 28 | /* 29 | (from to help 三个柱子) 30 | 1-n-1 from -> help 31 | 单n from -> to 32 | 1-n-1 help -> to 33 | 34 | 一个汉诺塔问题需要2^n -1 步数 35 | 因为要求打印所有的步数,所以时间复杂度就是O(2^n) 36 | */ 37 | -------------------------------------------------------------------------------- /src/base/sort/_01BubbleSort.java: -------------------------------------------------------------------------------- 1 | package base.sort; 2 | 3 | /* 4 | 冒泡排序算法 5 | 6 | 给定一个int数组A,请返回排序后的数组。 7 | 8 | 测试样例: 9 | 10 | [1,2,3,5,2,3] 11 | [1,2,2,3,3,5] 12 | */ 13 | public class _01BubbleSort { 14 | 15 | public static void bubbleSort(int[] array) { 16 | if (array == null || array.length <= 0) return; 17 | for (int p = array.length - 1; p >= 0; p--) { 18 | for (int i = 0; i < p; i++) {//前一个和后面一个比较,故到倒数第二个位置 19 | if (array[i] > array[i + 1]) { 20 | int temp = array[i]; 21 | array[i] = array[i + 1]; 22 | array[i + 1] = temp; 23 | } 24 | } 25 | } 26 | } 27 | 28 | public static void main(String[] args) { 29 | int[] array = {1, 2, 3, 5, 2, 3, 4, 8, 10, 20, 101, 98}; 30 | _01BubbleSort.bubbleSort(array); 31 | for (int i = 0; i < array.length; i++) { 32 | System.out.print(array[i] + " "); 33 | } 34 | } 35 | } 36 | 37 | 38 | //0~n-1比较,并将最大的沉底, 39 | //0~n-2比较,并将最大的沉底, 40 | //... 41 | //时间复杂度O(n^2) 42 | -------------------------------------------------------------------------------- /src/base/sort/_02SelectionSort.java: -------------------------------------------------------------------------------- 1 | package base.sort; 2 | 3 | //选择排序 4 | public class _02SelectionSort { 5 | public static void selectionSort(int[] array) { 6 | if (array == null || array.length <= 0) return; 7 | 8 | for (int i = 0; i < array.length; i++) { 9 | int min_index = i; 10 | for (int j = i + 1; j < array.length; j++) { //这个循环主要找到最小值的下标 11 | if (array[j] < array[min_index]) 12 | min_index = j; 13 | } 14 | int temp = array[i]; 15 | array[i] = array[min_index]; 16 | array[min_index] = temp; 17 | } 18 | 19 | } 20 | 21 | public static void main(String[] args) { 22 | int[] array = {1, 2, 3, 5, 3, 4, 8, 10, 20, 101, 98, 2}; 23 | _02SelectionSort.selectionSort(array); 24 | for (int i = 0; i < array.length; i++) { 25 | System.out.print(array[i] + " "); 26 | } 27 | } 28 | 29 | /** 30 | * 通用选择排序(泛型) 31 | * 32 | * @param array 33 | */ 34 | public static > void selectionSort_general(E[] array) { 35 | if (array == null || array.length <= 0) return; 36 | 37 | for (int i = 0; i < array.length; i++) { 38 | int min_index = i; 39 | for (int j = i + 1; j < array.length; j++) { //这个循环主要找到最小值的下标 40 | if (array[j].compareTo(array[min_index]) > 0) 41 | min_index = j; 42 | } 43 | E temp = array[i]; 44 | array[i] = array[min_index]; 45 | array[min_index] = temp; 46 | } 47 | 48 | } 49 | } 50 | 51 | 52 | //0~n-1 选择最小的放最前面 53 | //1~n-1 选择最小的放最前面 54 | //时间复杂度O(n^2) -------------------------------------------------------------------------------- /src/base/sort/_03InsertionSort.java: -------------------------------------------------------------------------------- 1 | package base.sort; 2 | 3 | //插入排序(其实质也需要移动) 4 | public class _03InsertionSort { 5 | public static void insertionSort(int[] array) { 6 | if (array == null || array.length <= 0) return; 7 | 8 | for (int i = 1; i < array.length; i++) { 9 | int current = i;//标记该数移动到哪个位置了 10 | for (int j = i - 1; j >= 0; j--) {//依次跟前面的数比较 11 | if (array[current] < array[j]) { 12 | int temp = array[j]; 13 | array[j] = array[current]; 14 | array[current] = temp; 15 | current--; 16 | } else { 17 | break; 18 | } 19 | 20 | } 21 | } 22 | 23 | } 24 | 25 | 26 | public static void main(String[] args) { 27 | int[] array = {10, 9, 8, 8, 7, 12, 19, 20, 20}; 28 | _03InsertionSort.insertionSort(array); 29 | for (int i = 0; i < array.length; i++) { 30 | System.out.print(array[i] + " "); 31 | } 32 | } 33 | 34 | /** 35 | * 通用方法:会交换元素 36 | * 37 | * @param a 38 | * @param 39 | */ 40 | public static > void insertionSort_general(T[] a) { 41 | for (int i = 0; i < a.length; i++) { 42 | for (int j = i; j - 1 >= 0; j--) { 43 | if (a[j].compareTo(a[j - 1]) < 0) { 44 | T tmp = a[j]; 45 | a[j] = a[j - 1]; 46 | a[j - 1] = tmp; 47 | } else { 48 | break; 49 | } 50 | } 51 | } 52 | } 53 | 54 | /** 55 | * 最终版:不交换,取出数据依次后移,插入到准确位置 56 | * 57 | * @param a 58 | * @param 59 | */ 60 | public static > void insertionSort_final(T[] a) { 61 | for (int i = 0; i < a.length; i++) { 62 | T tmp = a[i]; 63 | int j; 64 | for (j = i; j - 1 >= 0 && tmp.compareTo(a[j - 1]) < 0; j--) { 65 | a[j] = a[j - 1]; 66 | } 67 | a[j] = tmp; 68 | } 69 | } 70 | } 71 | 72 | 73 | //1和0比较,若小往前移动 74 | //2依次和前面的比较,插入到对应的位置 75 | //O(n^2) -------------------------------------------------------------------------------- /src/base/sort/_05QuickSort.java: -------------------------------------------------------------------------------- 1 | package base.sort; 2 | 3 | //快速排序 4 | public class _05QuickSort { 5 | public static void quickSort(int[] array) { 6 | if (array == null || array.length <= 0) return; 7 | quick(array, 0, array.length - 1); 8 | 9 | } 10 | 11 | private static void quick(int[] array, int start, int end) { 12 | if (start < end) { 13 | int index = quick_core(array, start, end); 14 | quick(array, start, index - 1); 15 | quick(array, index + 1, end); 16 | } 17 | } 18 | 19 | 20 | //划分位置 21 | private static int quick_core(int[] array, int start, int end) { 22 | int key = array[end]; 23 | int i = start - 1; 24 | while (start < end) { 25 | if (array[start] <= array[end]) { 26 | int temp = array[i + 1]; 27 | array[i + 1] = array[start]; 28 | array[start] = temp; 29 | i++; 30 | } 31 | start++; 32 | } 33 | int temp = array[i + 1]; 34 | array[i + 1] = array[end]; 35 | array[end] = temp; 36 | return i + 1; 37 | } 38 | 39 | 40 | public static void main(String[] args) { 41 | int[] array = {54, 35, 48, 36, 27, 12, 44, 44, 8, 14, 26, 17, 28}; 42 | _05QuickSort.quickSort(array); 43 | for (int i = 0; i < array.length; i++) { 44 | System.out.print(array[i] + " "); 45 | } 46 | } 47 | } 48 | 49 | 50 | //随机选择一个数,小的放左边,大的放右边 51 | //两边分别递归的调用该方法 52 | 53 | //划分值放在最后的位置,最前面设定划分池 54 | //从头开始遍历,如果当前数大于划分值,则不动;如果小于划分值,则跟划分池外的第一个数交换,划分值扩大1 55 | //遍历完之后,划分值和划分池外面的第一个数交换 56 | //O(n*logn) -------------------------------------------------------------------------------- /src/base/sort/_06HeapSort.java: -------------------------------------------------------------------------------- 1 | package base.sort; 2 | 3 | //堆排序 4 | public class _06HeapSort { 5 | 6 | public static void heapSort(int[] array) { 7 | int n = array.length; 8 | 9 | //先进行堆初始化 10 | for (int i = n / 2 - 1; i >= 0; --i) //从最后一个父节点开始,依次往前面的父节点初始化 11 | heapAdjust(array, i, n - 1); 12 | for (int i = n - 1; i > 0; i--) {//调整的次数 13 | 14 | int temp = array[0];//将最大值交换到最后面,此时最后一个数已经为现堆中的最大值 15 | array[0] = array[i]; 16 | array[i] = temp; 17 | heapAdjust(array, 0, i - 1); 18 | } 19 | 20 | } 21 | 22 | 23 | //这是堆调整的过程,而非初始化堆的过程 24 | private static void heapAdjust(int[] array, int parent, int n) { 25 | int temp = array[parent];//保存父节点的值 26 | for (int i = 2 * parent + 1; i <= n; i = 2 * i + 1) {//从子节点开始找子树依次往后遍历(找子节点中大的) 27 | if (i < n && array[i] < array[i + 1])//i array[i]) //说明最上方的数依然是最大的数,所以最大堆依然是成立的,故不需要继续调整 其实就是将temp这个点插入到合适的位置 30 | break; 31 | array[parent] = array[i]; 32 | parent = i;//坐标指向孩子 33 | } 34 | array[parent] = temp;//此时的parent指向的是当前坐标 35 | 36 | 37 | } 38 | 39 | 40 | public static void main(String[] args) { 41 | int[] array = {4, 5, 3, 0, 1, 7, 2, 6}; 42 | _06HeapSort.heapSort(array); 43 | for (int i = 0; i < array.length; i++) { 44 | System.out.print(array[i] + " "); 45 | } 46 | } 47 | } 48 | 49 | 50 | /*将数组调整为大根堆,此时最大值在上方(对应的数组顺序是层次遍历) 51 | 将最大值和数组中的最后一个数交换位置,此时最大值固定,脱离最大堆 52 | 对剩下的堆进行最大堆的调整,重复上面的步骤 53 | */ 54 | 55 | /* 56 | 堆化数组的过程: 57 | 从最后一个父节点开始,向前遍历每一个父节点,每一次调用调整最大堆核心代码(从最后一个父节点开始,调整好几次) 58 | 59 | 调整最大堆的过程(核心代码) 60 | 从第一个节点开始,保存父节点的值,找到他的两个儿子中大的那个,如果父 > 子 ,调出循环;如果父 < 子,则用子的值替换父的值 61 | 然后往下找子节点,同上覆盖值,直到合适的位置,将之前保存的父亲的值插入,即小值下沉的过程 62 | 63 | */ 64 | 65 | -------------------------------------------------------------------------------- /src/base/sort/_07ShellSort.java: -------------------------------------------------------------------------------- 1 | package base.sort; 2 | 3 | //希尔排序 4 | public class _07ShellSort { 5 | public static void shellSort(int[] a) { 6 | if (a == null || a.length <= 0) return; 7 | int n = a.length; 8 | for (int gap = n / 2; gap > 0; gap /= 2) {//gap为步长 9 | for (int i = gap; i < n; i++) { 10 | int temp = a[i];//保存当前位置的值 11 | int k = i - gap;//标记每次向前移动步长的位置 12 | while (k >= 0 && temp < a[k]) {//未到头且比前面位置的小 13 | a[k + gap] = a[k];//后面的数设为前面的数,从此开始的后几步思想和堆里面的思想有点像,就是把最小的放前 14 | k -= gap; 15 | } 16 | a[k + gap] = temp;//将temp值放入移动到的位置,即前面的数比他小了,移不动了 17 | } 18 | } 19 | 20 | } 21 | 22 | public static void main(String[] args) { 23 | int[] array = {4, 5, 3, 0, 1, 7, 2, 6}; 24 | _07ShellSort.shellSort(array); 25 | for (int i = 0; i < array.length; i++) { 26 | System.out.print(array[i] + " "); 27 | } 28 | } 29 | } 30 | 31 | 32 | //希尔排序是插入排序的改良,核心:设置步长 33 | 34 | -------------------------------------------------------------------------------- /src/base/unionfind/岛问题.java: -------------------------------------------------------------------------------- 1 | package base.unionfind; 2 | 3 | /* 4 | 一个矩阵中只有0和1两种值, 每个位置都可以和自己的上、 下、 左、 右 5 | 四个位置相连, 如果有一片1连在一起, 这个部分叫做一个岛, 求一个 6 | 矩阵中有多少个岛? 7 | 举例: 8 | 0 0 1 0 1 0 9 | 1 1 1 0 1 0 10 | 1 0 0 1 0 0 11 | 0 0 0 0 0 0 12 | 这个矩阵中有三个岛。 13 | */ 14 | public class 岛问题 { 15 | //法一:感染法,单核cpu跑,双重for循环 16 | public static int countIslands(int[][] arr) { 17 | int count = 0; 18 | for (int i = 0; i < arr.length; i++) { 19 | for (int j = 0; j < arr[0].length; j++) { 20 | if (arr[i][j] == 1) { 21 | count++; 22 | infect(arr, i, j);//周围的有1的都置为2 23 | } 24 | } 25 | } 26 | return count; 27 | } 28 | 29 | private static void infect(int[][] arr, int i, int j) { 30 | //base case 以下情况直接返回 31 | if (i < 0 || i >= arr.length || j < 0 || j >= arr[0].length || arr[i][j] != 1) { 32 | return; 33 | } 34 | arr[i][j] = 2; 35 | infect(arr, i + 1, j); 36 | infect(arr, i - 1, j); 37 | infect(arr, i, j + 1); 38 | infect(arr, i, j - 1); 39 | } 40 | 41 | //法二:并查集,拆分成几块,适合数据较大的情况 42 | 43 | 44 | public static void main(String[] args) { 45 | int[][] m = { 46 | {0, 0, 0, 0, 0, 0, 0, 0, 0}, 47 | {0, 1, 1, 1, 0, 1, 1, 1, 0}, 48 | {0, 1, 1, 1, 0, 0, 0, 1, 0}, 49 | {0, 1, 1, 0, 0, 0, 0, 0, 0}, 50 | {0, 0, 0, 0, 0, 1, 1, 0, 0}, 51 | {0, 0, 0, 0, 1, 1, 1, 0, 0}, 52 | {0, 0, 0, 0, 0, 0, 0, 0, 0} 53 | }; 54 | System.out.println(countIslands(m)); 55 | } 56 | } 57 | 58 | /* 59 | 并查集的思想 60 | 将矩阵分成几块,然后每一块查找岛屿,将1相连,最后合并的时候减去边界在一起的 61 | */ -------------------------------------------------------------------------------- /src/ctci/_1_1Different.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | import java.util.Arrays; /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请实现一个算法,确定一个字符串的所有字符是否全都不同。这里我们要求不允许使用额外的存储结构。 26 | * 给定一个string iniString,请返回一个bool值,True代表所有字符全都不同,False代表存在相同的字符。保证字符串中的字符为ASCII字符。字符串的长度小于等于3000。 27 | */ 28 | //@formatter:on 29 | public class _1_1Different { 30 | public boolean checkDifferent(String iniString) { 31 | char[] chars = iniString.toCharArray(); 32 | Arrays.sort(chars); 33 | for (int i = 0; i < chars.length - 1; i++) { 34 | if (chars[i] == chars[i + 1]) 35 | return false; 36 | } 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ctci/_1_2Reverse.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请实现一个算法,在不使用额外数据结构和储存空间的情况下,翻转一个给定的字符串(可以使用单个过程变量)。 26 | * 给定一个string iniString,请返回一个string,为翻转后的字符串。保证字符串的长度小于等于5000。 27 | */ 28 | //@formatter:on 29 | 30 | public class _1_2Reverse { 31 | public String reverseString(String iniString) { 32 | if (iniString == null) return iniString; 33 | char[] chars = iniString.toCharArray(); 34 | int len = chars.length; 35 | int mid = 0 + (len - 1 - 0) / 2; 36 | int index = len % 2 == 0 ? mid : mid - 1; //看是mid还是mid前面那个数 37 | for (int i = 0; i <= index; i++) { 38 | swap(chars, i, len - i - 1); 39 | } 40 | return String.valueOf(chars); 41 | } 42 | 43 | private void swap(char[] chars, int i, int j) { 44 | char temp = chars[i]; 45 | chars[i] = chars[j]; 46 | chars[j] = temp; 47 | } 48 | 49 | public static void main(String[] args) { 50 | String s = "abcde"; 51 | _1_2Reverse instance = new _1_2Reverse(); 52 | String s1 = instance.reverseString(s); 53 | System.out.println(s1); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ctci/_1_6Transform.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。 26 | * 给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转后的NxN矩阵,保证N小于等于500,图像元素小于等于256。 27 | */ 28 | //@formatter:on 29 | public class _1_6Transform { 30 | //上下交换,然后按照主对角线交换 31 | public int[][] transformImage(int[][] mat, int n) { 32 | if (mat == null) return null; 33 | int rows = mat.length; 34 | int cols = mat[0].length; 35 | //按上下交换 36 | for (int i = 0; i < rows / 2; i++) { 37 | for (int j = 0; j < cols; j++) { 38 | int temp = mat[i][j]; 39 | mat[i][j] = mat[cols - i - 1][j]; 40 | mat[cols - i - 1][j] = temp; 41 | } 42 | } 43 | //再按对角线交换 44 | for (int i = 0; i < cols; i++) { 45 | for (int j = i; j < cols; j++) { 46 | int temp = mat[i][j]; 47 | mat[i][j] = mat[j][i]; 48 | mat[j][i] = temp; 49 | } 50 | } 51 | return mat; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/ctci/_1_7Clearer.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请编写一个算法,若N阶方阵中某个元素为0,则将其所在的行与列清零。 26 | * 给定一个N阶方阵int[][] mat和矩阵的阶数n, 27 | * 请返回完成操作后的int[][]方阵,保证n小于等于300,矩阵中的元素为int范围内。 28 | * [[1,2,3],[0,1,2],[0,0,1]] 返回:[[0,0,3],[0,0,0],[0,0,0]] 29 | */ 30 | //@formatter:on 31 | public class _1_7Clearer { 32 | public int[][] clearZero(int[][] mat, int n) { 33 | //定义行列两个数组 34 | boolean[] row = new boolean[n]; 35 | boolean[] col = new boolean[n]; 36 | for (int i = 0; i < n; i++) { 37 | for (int j = 0; j < n; j++) { 38 | if (mat[i][j] == 0) { 39 | row[i] = true; 40 | col[j] = true; 41 | } 42 | } 43 | } 44 | for (int i = 0; i < n; i++) { 45 | for (int j = 0; j < n; j++) { 46 | if (row[i] == true || col[j] == true) { 47 | mat[i][j] = 0; 48 | } 49 | } 50 | } 51 | return mat; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/ctci/_1_8ReverseEqual.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | import java.util.Arrays; /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串。请将这个算法编写成一个函数,给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只能调用一次检查子串的函数。 26 | * 给定两个字符串s1,s2,请返回bool值代表s2是否由s1旋转而成。字符串中字符为英文字母和空格,区分大小写,字符串长度小于等于1000。 27 | */ 28 | //@formatter:on 29 | public class _1_8ReverseEqual { 30 | public boolean checkReverseEqual(String s1, String s2) { 31 | if (s1.length() != s2.length()) return false; 32 | char[] chars1 = s1.toCharArray(); 33 | char[] chars2 = s2.toCharArray(); 34 | Arrays.sort(chars1); 35 | Arrays.sort(chars2); 36 | for (int i = 0; i < chars1.length; i++) { 37 | if (chars1[i] != chars2[i]) 38 | return false; 39 | } 40 | return true; 41 | 42 | } 43 | 44 | //法二:将s1变成s1s1,若s2是翻转子串一定被包含 45 | public boolean checkReverseEqual_2(String s1, String s2) { 46 | if (s1.length() != s2.length()) return false; 47 | String str = s1 + s1; 48 | if (str.contains(s2)) 49 | return true; 50 | else return false; 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/ctci/_2_2FindKthToTail.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一个链表,输出该链表中倒数第k个结点。 26 | */ 27 | //@formatter:on 28 | 29 | class ListNode { 30 | int val; 31 | ListNode next = null; 32 | 33 | ListNode(int val) { 34 | this.val = val; 35 | } 36 | } 37 | 38 | public class _2_2FindKthToTail { 39 | //这题不难,利用快慢指针,主要是对一些k的边界条件的去除 40 | public ListNode FindKthToTail(ListNode head, int k) { 41 | if (head == null || k == 0) 42 | return null; 43 | ListNode fast = head; 44 | ListNode slow = head; 45 | while (k-- > 1) { 46 | fast = fast.next; 47 | if (fast == null) 48 | return null; 49 | 50 | } 51 | while (fast.next != null) { 52 | fast = fast.next; 53 | slow = slow.next; 54 | } 55 | return slow; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/ctci/_2_3removeNode.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:实现一个算法,删除单向链表中间的某个结点,假定你只能访问该结点。 26 | * 给定带删除的节点,请执行删除操作,若该节点为尾节点,返回false,否则返回true 27 | */ 28 | //@formatter:on 29 | public class _2_3removeNode { 30 | public boolean removeNode(ListNode pNode) { 31 | if (pNode.next == null) return false; 32 | pNode = pNode.next; 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ctci/_2_4Partition.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 26 | * 给定一个链表的头指针 ListNode* pHead,请返回重新排列后的链表的头指针。注意:分割以后保持原来的数据顺序不变。 27 | */ 28 | //@formatter:on 29 | public class _2_4Partition { 30 | public ListNode partition(ListNode pHead, int x) { 31 | if (pHead == null) return null; 32 | ListNode preHead = new ListNode(-1); 33 | preHead.next = pHead; 34 | ListNode pre = preHead; 35 | ListNode cur = pHead; 36 | ListNode npre = new ListNode(-1); 37 | ListNode ncur = npre; 38 | while (cur != null) { 39 | if (cur.val < x) { 40 | pre.next = cur.next; 41 | cur.next = null; 42 | ncur.next = cur; 43 | ncur = ncur.next; 44 | cur = pre.next;//更新cur的指向 45 | } else { 46 | pre = pre.next; 47 | cur = pre.next; 48 | } 49 | } 50 | ncur.next = preHead.next; 51 | return npre.next; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/ctci/_2_5Plus.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有两个用链表表示的整数,每个结点包含一个数位。 26 | * 这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。 27 | * 给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)。 28 | */ 29 | //@formatter:on 30 | public class _2_5Plus { 31 | public ListNode plusAB(ListNode a, ListNode b) { 32 | int one = 0; 33 | int two = 0; 34 | int tens = 0;//10的次方 35 | while (a != null) { 36 | one += a.val * Math.pow(10, tens); 37 | a = a.next; 38 | tens++; 39 | } 40 | tens = 0; 41 | while (b != null) { 42 | two += b.val * Math.pow(10, tens); 43 | b = b.next; 44 | tens++; 45 | } 46 | int c = one + two; 47 | ListNode preHead = new ListNode(-1); 48 | ListNode p = preHead; 49 | int place_value = Integer.MIN_VALUE;//一个位置上的值 50 | while (c > 0) { 51 | place_value = c % 10; 52 | ListNode nextNode = new ListNode(place_value); 53 | p.next = nextNode; 54 | p = p.next; 55 | c /= 10; 56 | } 57 | return preHead.next; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/ctci/_2_5Plus_2.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有两个用链表表示的整数,每个结点包含一个数位。 26 | * 这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。 27 | * 给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)。 28 | */ 29 | //@formatter:on 30 | public class _2_5Plus_2 { 31 | public ListNode plusAB(ListNode a, ListNode b) { 32 | ListNode preHead = new ListNode(-100); 33 | ListNode p = preHead; 34 | int carry = 0;//定义进位 35 | while (a != null || b != null || carry != 0) { 36 | int a_value = (a == null) ? 0 : a.val; 37 | int b_value = (b == null) ? 0 : b.val; 38 | int sum = a_value + b_value + carry; 39 | carry = sum / 10; 40 | ListNode p_next = new ListNode(sum % 10); 41 | p.next = p_next; 42 | p = p_next; 43 | a = (a == null) ? a : a.next; 44 | b = (b == null) ? b : b.next; 45 | } 46 | return preHead.next; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/ctci/_2_7Palindrome.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | import java.util.Stack; /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请编写一个函数,检查链表是否为回文。给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文。 26 | */ 27 | //@formatter:on 28 | public class _2_7Palindrome { 29 | public boolean isPalindrome(ListNode pHead) { 30 | if (pHead == null) return true; 31 | ListNode p = pHead; 32 | int count = 0; 33 | while (p != null) { 34 | count++; 35 | p = p.next; 36 | } 37 | p = pHead; 38 | ListNode q = pHead; 39 | int mid = 1 + (count - 1) / 2;//快指针开始的下标 40 | while (mid-- > 0) 41 | q = q.next; 42 | Stack stack = new Stack<>(); 43 | while (q != null) { 44 | stack.push(q.val); 45 | q = q.next; 46 | } 47 | while (!stack.isEmpty()) { 48 | Integer data = stack.pop(); 49 | if (data != p.val) return false; 50 | p = p.next; 51 | } 52 | return true; 53 | } 54 | } 55 | 56 | /* 57 | 快慢指针+栈 58 | */ 59 | -------------------------------------------------------------------------------- /src/ctci/_3_5stackQueue.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.Stack; 30 | 31 | public class _3_5stackQueue { 32 | Stack stack1 = new Stack(); 33 | Stack stack2 = new Stack(); 34 | 35 | public void push(int node) { 36 | stack1.push(node); 37 | } 38 | 39 | public int pop() { 40 | if (stack2.size() != 0) return stack2.pop();//2中有值肯定先用这里的值pop 41 | while (stack1.size() != 0) { 42 | int data = stack1.pop(); 43 | stack2.push(data); 44 | } 45 | return stack2.pop(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ctci/_3_6twoStacksSort.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:按升序对栈进行排序(即最大元素位于栈顶),要求最多只能使用一个额外的栈存放临时数据,但不得将元素复制到别的数据结构中。 26 | * 数组的第一个数为栈顶 27 | */ 28 | //@formatter:on 29 | 30 | import java.util.ArrayList; 31 | import java.util.Stack; 32 | 33 | public class _3_6twoStacksSort { 34 | //构建一个辅助栈存放排好序的(栈头是最大值) 和 一个变量存放临时值 35 | public ArrayList twoStacksSort(int[] numbers) { 36 | ArrayList res = new ArrayList<>(); 37 | if (numbers == null || numbers.length == 0) return res; 38 | Stack stack1 = new Stack<>();//原始栈 39 | for (int i = numbers.length - 1; i >= 0; i--) 40 | stack1.push(numbers[i]); 41 | int temp;//存放临时值 42 | Stack stack2 = new Stack<>(); 43 | while (stack1.size() != 0) { 44 | temp = stack1.pop(); 45 | while (stack2.size() != 0 && stack2.peek() > temp) {//辅助栈不为空,且栈头元素比临时值大 46 | stack1.push(stack2.pop()); 47 | } 48 | stack2.push(temp); 49 | } 50 | 51 | while (stack2.size() != 0) { 52 | res.add(stack2.pop()); 53 | } 54 | return res; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ctci/_4_1Balance.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1。 26 | * 给定指向树根结点的指针TreeNode* root,请返回一个bool,代表这棵树是否平衡。 27 | */ 28 | //@formatter:on 29 | class TreeNode { 30 | int val = 0; 31 | TreeNode left = null; 32 | TreeNode right = null; 33 | 34 | public TreeNode(int val) { 35 | this.val = val; 36 | } 37 | } 38 | 39 | public class _4_1Balance { 40 | //法一:比较每一层的左右子树的深度 41 | public boolean isBalance(TreeNode root) { 42 | if (root == null) return true; 43 | int left = depth(root.left); 44 | int right = depth(root.right); 45 | int diff = left - right; 46 | if (diff < -1 || diff > 1) 47 | return false; 48 | return isBalance(root.left) && isBalance(root.right); 49 | } 50 | 51 | private int depth(TreeNode node) { 52 | if (node == null) return 0; 53 | int left = depth(node.left); 54 | int right = depth(node.right); 55 | return left > right ? left + 1 : right + 1; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/ctci/_4_1Balance_2.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1。 26 | * 给定指向树根结点的指针TreeNode* root,请返回一个bool,代表这棵树是否平衡。 27 | */ 28 | //@formatter:on 29 | 30 | public class _4_1Balance_2 { 31 | //法二:后序遍历 32 | private boolean isBalance = true; 33 | 34 | public boolean isBalance(TreeNode root) { 35 | if (root == null) return true; 36 | //isBalance(root.left);这两步不要了,因为下面的代码已经实现了后续遍历 37 | //isBalance(root.right); 38 | depth(root); 39 | return isBalance; 40 | } 41 | 42 | 43 | private int depth(TreeNode node) { 44 | if (node == null) return 0; 45 | int left = depth(node.left); 46 | int right = depth(node.right); 47 | if (Math.abs(left - right) > 1) 48 | isBalance = false; 49 | return left - right > 0 ? left + 1 : right + 1; 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/ctci/_4_3buildMinimalBST.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:对于一个元素各不相同且按升序排列的有序序列,请编写一个算法,创建一棵高度最小的二叉查找树。 26 | * 给定一个有序序列int[] vals,请返回创建的二叉查找树的高度。 27 | */ 28 | //@formatter:on 29 | public class _4_3buildMinimalBST { 30 | 31 | public int buildMinimalBST(int[] vals) { 32 | if (vals == null) return 0; 33 | TreeNode root = helper(vals, 0, vals.length - 1); 34 | return getDepth(root); 35 | } 36 | 37 | private TreeNode helper(int[] vals, int start, int end) { 38 | if (start > end) { 39 | return null; 40 | } 41 | int mid = start + (end - start) / 2; 42 | TreeNode father = new TreeNode(vals[mid]); 43 | father.left = helper(vals, start, mid - 1); 44 | father.right = helper(vals, mid + 1, end); 45 | 46 | return father; 47 | } 48 | 49 | private int getDepth(TreeNode root) { 50 | if (root == null) return 0; 51 | int left = getDepth(root.left); 52 | int right = getDepth(root.right); 53 | return left > right ? left + 1 : right + 1; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ctci/_4_4TreeLevel.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表。 26 | * 给定二叉树的根结点指针TreeNode* root,以及链表上结点的深度,请返回一个链表ListNode,代表该深度上所有结点的值, 27 | * 请按树上从左往右的顺序链接,保证深度不超过树的高度,树上结点的值为非负整数且不超过100000。 28 | */ 29 | //@formatter:on 30 | public class _4_4TreeLevel { 31 | //刚开始深度为dep,每往下递归一层,深度-1,当dep == 1时,便输出元素 32 | ListNode pre = new ListNode(-1); 33 | ListNode p = pre;//一个指针 34 | 35 | public ListNode getTreeLevel(TreeNode root, int dep) { 36 | if (root == null || dep <= 0) return null; 37 | if (dep == 1) { 38 | p.next = new ListNode(root.val); 39 | p = p.next; 40 | } else { 41 | //前序遍历,先左后右实现从左到右打印 42 | getTreeLevel(root.left, dep - 1); 43 | getTreeLevel(root.right, dep - 1); 44 | } 45 | return pre.next; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ctci/_4_5checkBST.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请实现一个函数,检查一棵二叉树是否为二叉查找树。 26 | * 给定树的根结点指针TreeNode* root,请返回一个bool,代表该树是否为二叉查找树。 27 | */ 28 | //@formatter:on 29 | 30 | 31 | public class _4_5checkBST { 32 | //中序遍历 保存上一个元素的值 33 | int last = Integer.MIN_VALUE; 34 | 35 | public boolean checkBST(TreeNode root) { 36 | if (root == null) return true; 37 | if (!checkBST(root.left)) return false; //左 如果上一层返回的是false,则直接返回false 38 | if (root.val < last) return false; 39 | last = root.val; 40 | if (!checkBST(root.right)) return false; //右 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ctci/_4_6Successor.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。 26 | * 给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。 27 | * 保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。 28 | */ 29 | //@formatter:on 30 | public class _4_6Successor { 31 | boolean flag = false;//当flag为真时,则表示找到了该数 32 | 33 | public int findSucc(TreeNode root, int p) { 34 | return helper(root, p); 35 | } 36 | 37 | private int helper(TreeNode root, int p) { 38 | if (root == null) return -1; 39 | int left = helper(root.left, p);//返回的是左儿子的值 40 | if (left != -1) return left; 41 | if (flag == true) return root.val;//找到这个值了(其实已经是这个值的下一个节点了,因为在后面一句话置true)则返回当前的值,那么到了上一层被上一句代码拦截,就返回left 42 | if (root.val == p) flag = true; 43 | return helper(root.right, p); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/ctci/_4_6Successor_2.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。 26 | * 给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。 27 | * 保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。 28 | */ 29 | //@formatter:on 30 | public class _4_6Successor_2 { 31 | TreeNode pre = new TreeNode(-1);//前驱指针 32 | 33 | public int findSucc(TreeNode root, int p) { 34 | if (root == null) return -1;//空 35 | int left = findSucc(root.left, p);//一路到最左边叶子节点,得到的是左儿子的值 36 | if (left == -1) { 37 | //pre指向最左边,root为后继节点 38 | if (pre.val == p) { 39 | return root.val; 40 | } 41 | pre = root;//如果前一个节点不是,则pre指向root的对象 42 | return findSucc(root.right, p); 43 | } 44 | //如果找不到则返回上一层的根节点 45 | return left; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ctci/_4_7LCA.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有一棵无穷大的满二叉树,其结点按根结点一层一层地从左往右依次编号,根结点编号为1。求出a和b点的最近公共祖先的编号。 26 | * 给定两个int TrieTree,b。为给定结点的编号。请返回a和b的最近公共祖先的编号。注意这里结点本身也可认为是其祖先。 27 | */ 28 | //@formatter:on 29 | public class _4_7LCA { 30 | //谁大谁除以2 31 | public int getLCA(int a, int b) { 32 | while (a != b) { 33 | if (a > b) a /= 2; 34 | if (b > a) b /= 2; 35 | } 36 | return a; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ctci/_4_9FindPath.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 26 | * 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 27 | */ 28 | //@formatter:on 29 | 30 | import java.util.ArrayList; 31 | 32 | public class _4_9FindPath { 33 | public static int sum = 0; 34 | ArrayList> res = new ArrayList<>(); 35 | ArrayList path = new ArrayList<>(); 36 | 37 | public ArrayList> FindPath(TreeNode root, int target) { 38 | if (root == null) return res; 39 | path.add(root.val); 40 | sum += root.val; 41 | if (sum == target && root.left == null && root.right == null) { 42 | res.add(new ArrayList<>(path)); 43 | } 44 | FindPath(root.left, target); 45 | FindPath(root.right, target); 46 | path.remove(path.size() - 1); 47 | sum -= root.val; 48 | return res; 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/ctci/_4_9FindPath_2.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 26 | * 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 27 | */ 28 | //@formatter:on 29 | 30 | import java.util.ArrayList; 31 | 32 | public class _4_9FindPath_2 { 33 | private ArrayList> res = new ArrayList<>(); 34 | private ArrayList list = new ArrayList<>(); 35 | 36 | public ArrayList> FindPath(TreeNode root, int target) { 37 | if (root == null) return res; 38 | target -= root.val; 39 | list.add(root.val); 40 | if (target == 0 && root.left == null && root.right == null) { 41 | res.add(new ArrayList<>(list)); 42 | } 43 | FindPath(root.left, target); 44 | FindPath(root.right, target); 45 | list.remove(list.size() - 1); 46 | return res; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/ctci/_5_1BinInsert.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有两个32位整数n和m,请编写算法将m的二进制数位插入到n的二进制的第j到第i位,其中二进制的位数从低位数到高位且以0开始。 26 | * 给定两个数int n和int m,同时给定int j和int i,意义如题所述,请返回操作后的数,保证n的第j到第i位均为零,且m的二进制位数小于等于i-j+1。 27 | * 测试样例:1024,19,2,6返回:1100 28 | */ 29 | //@formatter:on 30 | public class _5_1BinInsert { 31 | public int binInsert(int n, int m, int j, int i) { 32 | m <<= j;//左移j位 33 | return m | n; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ctci/_5_2BinDecimal.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述: 26 | * 有一个介于0和1之间的实数,类型为double,返回它的二进制表示。如果该数字无法精确地用32位以内的二进制表示,返回“Error”。 27 | * 给定一个double num,表示0到1的实数,请返回一个string,代表该数的二进制表示或者“Error”。 28 | * 测试样例:0.625返回:0.101 29 | */ 30 | //@formatter:on 31 | 32 | public class _5_2BinDecimal { 33 | public String printBin(double num) { 34 | StringBuilder sb = new StringBuilder(); 35 | sb.append("0."); 36 | while (true) { 37 | num = num * 2; 38 | sb.append(num >= 1 ? 1 : 0); 39 | if (num == 1) break; 40 | num = num > 1 ? num - 1 : num; 41 | } 42 | String res = sb.toString(); 43 | if (res.length() > 32) res = "Error"; 44 | return res; 45 | } 46 | } 47 | 48 | /* 49 | 十进制小数转二进制数:“乘以2取整,顺序排列”(乘2取整法) 50 | 小数部分: 51 | 0.625*2=1.25 (取整数) 52 | 0.25*2=0.5 53 | 0.5*2=1 54 | 然后我们将整数部分按从上往下的顺序书写就是:101 55 | 56 | 所以:(0.625)(十)=(0.101)(二) 57 | */ -------------------------------------------------------------------------------- /src/ctci/_5_3CloseNumber.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有一个正整数,请找出其二进制表示中1的个数相同、且大小最接近的那两个数。(一个略大,一个略小) 26 | * 给定正整数int x,请返回一个数组,代表所求的两个数(小的在前)。保证答案存在。 27 | * 测试样例:2返回:[1,4] 28 | */ 29 | //@formatter:on 30 | public class _5_3CloseNumber { 31 | public int[] getCloseNumber(int x) { 32 | int min = x - 1, max = x + 1; 33 | while (Integer.bitCount(x) != Integer.bitCount(min) && min >= 0) { 34 | min--; 35 | } 36 | 37 | while (Integer.bitCount(x) != Integer.bitCount(max)) { 38 | max++; 39 | } 40 | int arr[] = {min, max}; 41 | return arr; 42 | } 43 | } 44 | 45 | /* 46 | 这里主要学习Integer.bitCount(x) 还有一种位运算暂时未列出,可以参考书籍。 47 | */ -------------------------------------------------------------------------------- /src/ctci/_5_5Transform.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:编写一个函数,确定需要改变几个位,才能将整数A转变成整数B。给定两个整数int A,int B。请返回需要改变的数位个数。 26 | * 测试样例:10,5返回:4 27 | */ 28 | //@formatter:on 29 | public class _5_5Transform { 30 | public int calcCost(int A, int B) { 31 | int res = 0; 32 | if (A == B) return res; 33 | while (A != 0 || B != 0) { 34 | if ((A & 1) != (B & 1)) { 35 | res++; 36 | } 37 | if (A != 0) 38 | A >>= 1; 39 | if (B != 0) 40 | B >>= 1; 41 | } 42 | return res; 43 | } 44 | 45 | //法二 46 | public int calcCost1(int A, int B) { 47 | return Integer.bitCount(A ^ B); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ctci/_5_6Exchange.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请编写程序交换一个数的二进制的奇数位和偶数位。(使用越少的指令越好) 26 | * 给定一个int x,请返回交换后的数int。测试样例:10返回:5 27 | */ 28 | //@formatter:on 29 | public class _5_6Exchange { 30 | public int exchangeOddEven(int x) { 31 | return ((x & 0xaaaaaaaa) >>> 1 | (x & 0x55555555) << 1); 32 | } 33 | } 34 | 35 | 36 | 37 | /* 38 | 0xaaaaaaaa = 10101010101010101010101010101010 39 | 0x55555555 = 01010101010101010101010101010101 40 | 41 | 题目意思是数中奇偶位位数相等,而位上对应数字互换 42 |   (x&0xaaaaaaaa)>>>1就是把奇数位清0,偶数位移到奇数位 43 |   (x&0x55555555)<<1就是把偶数位清0,奇数位移到偶数位 44 | */ -------------------------------------------------------------------------------- /src/ctci/_5_7Finder.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:数组A包含了0到n的所有整数,但其中缺失了一个。对于这个问题,我们设定限制,使得一次操作无法取得数组number里某个整数的完整内容。唯一的可用操作是询问数组中第i个元素的二进制的第j位(最低位为第0位),该操作的时间复杂度为常数,请设计算法,在O(n)的时间内找到这个数。 26 | * 给定一个数组number,即所有剩下的数按从小到大排列的二进制各位的值,如A[0][1]表示剩下的第二个数二进制从低到高的第二位。同时给定一个int n,意义如题。请返回缺失的数。 27 | * 测试样例:[[0],[0,1]] 返回:1 28 | */ 29 | //@formatter:on 30 | public class _5_7Finder { 31 | public int findMissing(int[][] numbers, int n) { 32 | for (int i = 0; i < n; i++) 33 | if (i % 2 != numbers[i][0]) 34 | return i; 35 | return n; 36 | 37 | } 38 | } 39 | 40 | /* 41 | 因为已经是排好序的,所以数字肯定是奇偶不断交替,如果连续碰上奇数奇数则第二个奇数则为缺少的数字,同理偶数也是如此,如果遍历了number数组仍没有找到缺少的数那就是缺少n了。 42 | */ -------------------------------------------------------------------------------- /src/ctci/_5_8Render.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有一个单色屏幕储存在一维数组中,其中数组的每个元素代表连续的8位的像素的值,请实现一个函数,将第x到第y个像素涂上颜色(像素标号从零开始),并尝试尽量使用最快的办法。 26 | * 给定表示屏幕的数组screen(数组中的每个元素代表连续的8个像素,且从左至右的像素分别对应元素的二进制的从低到高位),以及int x,int y,意义如题意所述,保证输入数据合法。请返回涂色后的新的屏幕数组。 27 | * 测试样例:[0,0,0,0,0,0],0,47 返回:[255,255,255,255,255,255] 28 | */ 29 | //@formatter:on 30 | public class _5_8Render { 31 | public int[] renderPixel(int[] screen, int x, int y) { 32 | for (int i = x; i <= y; i++) { 33 | int k = i % 8; //计算位置 34 | int t = i / 8; //计算索引 35 | screen[t] = screen[t] | (1 << k); //该位置如果是0则变成1,如果是1则仍为1 36 | } 37 | return screen; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ctci/_7_7KthNumber.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有一些数的素因子只有3、5、7,请设计一个算法,找出其中的第k个数。 26 | * 给定一个数int k,请返回第k个数。保证k小于等于100。 27 | */ 28 | //@formatter:on 29 | public class _7_7KthNumber { 30 | public int findKth(int k) { 31 | if (k <= 0) return 0; 32 | int[] a = new int[k]; 33 | int i3 = 0; 34 | int i5 = 0; 35 | int i7 = 0; 36 | a[0] = 3; 37 | a[1] = 5; 38 | a[2] = 7; 39 | for (int i = 3; i < k; i++) { 40 | int min = Math.min(a[i3] * 3, Math.min(a[i5] * 5, a[i7] * 7)); 41 | a[i] = min; 42 | if (min == a[i3] * 3) i3++; 43 | if (min == a[i5] * 5) i5++; 44 | if (min == a[i7] * 7) i7++; 45 | } 46 | return a[k - 1]; 47 | } 48 | } 49 | 50 | /* 51 | 思路:每个数都要乘三个数; 52 | 也可以使用队列来做 53 | */ 54 | -------------------------------------------------------------------------------- /src/ctci/_9_2_1Robot.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。 26 | * 请设计一个算法,计算机器人有多少种走法。 27 | * 给定两个正整数int x,int y,请返回机器人的走法数目。保证x+y小于等于12。 28 | */ 29 | //@formatter:on 30 | public class _9_2_1Robot { 31 | public static int countWays(int x, int y) { 32 | return helper(0, 0, x, y); 33 | } 34 | 35 | private static int helper(int i, int j, int x, int y) { 36 | if (i < 0 || j < 0 || i >= x || j >= y) return 0; 37 | if (i == x - 1 && j == y - 1) return 1;//到达目的地说明多了一种情况 38 | return helper(i + 1, j, x, y) + helper(i, j + 1, x, y); 39 | } 40 | 41 | public static void main(String[] args) { 42 | int x = 2; 43 | int y = 2; 44 | int i = _9_2_1Robot.countWays(x, y); 45 | System.out.println(i); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/ctci/_9_3_1MagicIndex.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个升序数组,元素值各不相同, 26 | * 编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。 27 | * 给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。 28 | * 测试样例:[1,2,3,4,5]返回:false 29 | */ 30 | //@formatter:on 31 | public class _9_3_1MagicIndex { 32 | //此方法顺序查找,复杂度 = o(n) 不满足题意 33 | /* public boolean findMagicIndex(int[] A, int n) { 34 | for (int i = 0; i < A.length; i++) { 35 | if (A[i] == i) { 36 | return true; 37 | } 38 | } 39 | return false; 40 | }*/ 41 | 42 | //二分查找 43 | public boolean findMagicIndex(int[] A, int n) { 44 | if (n == 0) return true; 45 | return helper(A, 0, n - 1); 46 | } 47 | 48 | private boolean helper(int[] a, int start, int end) { 49 | if (start >= end) return false; 50 | int mid = start + (end - start) / 2; 51 | if (a[mid] == mid) return true; 52 | else if (mid < a[mid]) return helper(a, start, mid); 53 | else return helper(a, mid + 1, end); 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ctci/_9_3_2MagicIndex.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个不下降序列,元素值可能相同, 26 | * 编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。 27 | * 给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。 28 | * 测试样例:[1,1,3,4,5]返回:true 29 | */ 30 | //@formatter:on 31 | public class _9_3_2MagicIndex { 32 | public boolean findMagicIndex(int[] A, int n) { 33 | if (n == 0) return true; 34 | for (int i = 0; i < n; ) { 35 | if (A[i] == i) return true; 36 | else if (A[i] < i) i++; 37 | else i = A[i]; 38 | } 39 | return false; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/ctci/_9_4Subset_2.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请编写一个方法,返回某集合的所有非空子集。 26 | * 给定一个int数组A和数组的大小int n,请返回A的所有非空子集。保证A的元素个数小于等于20,且元素互异。各子集内部从大到小排序,子集之间字典逆序排序,见样例。 27 | * 测试样例:[123,456,789]返回:{[789,456,123],[789,456],[789,123],[789],[456 123],[456],[123]} 28 | */ 29 | //@formatter:on 30 | 31 | import java.util.ArrayList; 32 | import java.util.Arrays; 33 | 34 | public class _9_4Subset_2 { 35 | public ArrayList> getSubsets(int[] A, int n) { 36 | ArrayList> res = new ArrayList<>(); 37 | if (n == 0) return res; 38 | Arrays.sort(A); 39 | 40 | int size = (1 << n) - 1;//非空子集的个数 41 | for (int i = size; i >= 1; i--) { 42 | ArrayList subSet = new ArrayList<>(); 43 | for (int j = n - 1; j >= 0; j--) { 44 | if (((i >> j) & 1) == 1) 45 | subSet.add(A[j]); 46 | } 47 | res.add(subSet); 48 | } 49 | return res; 50 | } 51 | } 52 | 53 | 54 | /* 55 | 思路: 使用二进制 56 | 例如三个数,则2^3-1=7,用二进制表示为111,每一位上表示这个数字有没有 57 | */ 58 | -------------------------------------------------------------------------------- /src/ctci/_9_6Parenthesis.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | import java.util.Stack; /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:对于一个字符串,请设计一个算法,判断其是否为一个合法的括号串。 26 | * 给定一个字符串A和它的长度n,请返回一个bool值代表它是否为一个合法的括号串。 27 | * 测试样例:"(()())",6返回:true 28 | * 测试样例:"()TrieTree()()",7返回:false 29 | * 测试样例:"()(()()",7返回:false 30 | */ 31 | //@formatter:on 32 | public class _9_6Parenthesis { 33 | public boolean chkParenthesis(String A, int n) { 34 | int left = 0; 35 | int right = 0; 36 | for (int i = 0; i < n; i++) { 37 | if (A.charAt(i) != '(' && A.charAt(i) != ')') 38 | return false; 39 | if (A.charAt(i) == '(') left++; 40 | if (A.charAt(i) == ')') right++; 41 | } 42 | return left == right; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/ctci/_9_8Coins.java: -------------------------------------------------------------------------------- 1 | package ctci; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。 26 | * 给定一个int n,请返回n分有几种表示法。保证n小于等于100000,为了防止溢出,请将答案Mod 1000000007。 27 | * 6 28 | * 2 29 | */ 30 | //@formatter:on 31 | public class _9_8Coins { 32 | 33 | public int countWays(int n) { 34 | int[] dp = new int[n + 1]; 35 | int coins[] = {1, 5, 10, 25}; 36 | dp[0] = 1; 37 | 38 | for (int i = 0; i < 4; i++) 39 | for (int j = coins[i]; j <= n; j++) 40 | dp[j] = (dp[j] + dp[j - coins[i]]) % 1000000007; 41 | return dp[n]; 42 | } 43 | } 44 | 45 | 46 | /* 47 | i分有 dp[i]种表示方法 48 | 49 | */ 50 | -------------------------------------------------------------------------------- /src/leetcode/easy/_1TwoSum.java: -------------------------------------------------------------------------------- 1 | package leetcode.easy; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /* 7 | Given an array of integers, return indices of the two numbers such that they add up to TrieTree specific target. 8 | You may assume that each input would have exactly one solution, and you may not use the same element twice. 9 | 10 | Example: 11 | Given nums = [2, 7, 11, 15], target = 9, 12 | Because nums[0] + nums[1] = 2 + 7 = 9, 13 | return [0, 1]. 14 | */ 15 | public class _1TwoSum { 16 | //time O(n^2) space O(1) 17 | public int[] twoSum(int[] nums, int target) { 18 | for (int i = 0; i < nums.length; i++) { 19 | for (int j = i + 1; j < nums.length; j++) { 20 | if (nums[i] + nums[j] == target) { 21 | return new int[]{i, j}; 22 | } 23 | } 24 | } 25 | throw new IllegalArgumentException("No two sum solution"); 26 | } 27 | 28 | //time O(n) space O(n) two-pass 29 | public int[] twoSum_2(int[] nums, int target) { 30 | Map map = new HashMap<>(); 31 | for (int i = 0; i < nums.length; i++) 32 | map.put(nums[i], i); 33 | for (int i = 0; i < nums.length; i++) { 34 | int key = target - nums[i]; 35 | if (map.containsKey(key) && map.get(key) != i) 36 | return new int[]{i, map.get(key)}; 37 | } 38 | throw new IllegalArgumentException("No two sum solution"); 39 | } 40 | 41 | //time O(n) space O(n) one-pass:一边查找,一边存key-value 42 | public int[] twoSum_3(int[] nums, int target) { 43 | Map map = new HashMap<>(); 44 | for (int i = 0; i < nums.length; i++) { 45 | int key = target - nums[i]; 46 | if (map.containsKey(key) && map.get(key) != i) 47 | return new int[]{i, map.get(key)}; 48 | //若不存在,将当前值存入 49 | map.put(nums[i], i); 50 | } 51 | throw new IllegalArgumentException("No two sum solution"); 52 | } 53 | } 54 | 55 | /* 56 | 思路:key-value:数值-下标 57 | */ -------------------------------------------------------------------------------- /src/leetcode/easy/_7ReverseInteger.java: -------------------------------------------------------------------------------- 1 | package leetcode.easy; 2 | 3 | /* 4 | Given TrieTree 32-bit signed integer, reverse digits of an integer. 5 | Example 1: 6 | 7 | Input: 123 8 | Output: 321 9 | Example 2: 10 | 11 | Input: -123 12 | Output: -321 13 | Example 3: 14 | 15 | Input: 120 16 | Output: 21 17 | 18 | Note: 19 | Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows. 20 | 21 | */ 22 | public class _7ReverseInteger { 23 | public int reverse(int x) { 24 | int res = 0; 25 | while (x != 0) { 26 | if (Math.abs(res) > Integer.MAX_VALUE / 10) 27 | return 0; 28 | res = res * 10 + x % 10; 29 | x /= 10; 30 | } 31 | return res; 32 | } 33 | 34 | public static void main(String[] args) { 35 | int reverse = new _7ReverseInteger().reverse(1463847412); 36 | System.out.println(reverse); 37 | } 38 | } 39 | 40 | 41 | /* 42 | 关键点:如何处理越界的情况 43 | 因为2147483648最大,末尾是8,所有判断时,不加等号,不存在加上x%10越界的情况 44 | */ 45 | -------------------------------------------------------------------------------- /src/leetcode/easy/_9PalindromeNumber.java: -------------------------------------------------------------------------------- 1 | package leetcode.easy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /* 7 | Determine whether an integer is TrieTree palindrome. An integer is TrieTree palindrome when it reads the same backward as forward. 8 | 9 | Example 1: 10 | 11 | Input: 121 12 | Output: true 13 | Example 2: 14 | 15 | Input: -121 16 | Output: false 17 | Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not TrieTree palindrome. 18 | Example 3: 19 | 20 | Input: 10 21 | Output: false 22 | Explanation: Reads 01 from right to left. Therefore it is not TrieTree palindrome. 23 | Follow up: 24 | 25 | Coud you solve it without converting the integer to TrieTree string? 26 | 27 | 28 | */ 29 | public class _9PalindromeNumber { 30 | //将整数拆分成list,然后比较对应位置的值,但题中指出不使用String的方法 31 | public boolean isPalindrome(int x) { 32 | List list = new ArrayList<>(); 33 | if (x < 0) return false; 34 | while (x != 0) { 35 | list.add(x % 10); 36 | x /= 10; 37 | } 38 | for (int i = 0; i <= list.size() / 2 - 1; i++) { 39 | if (list.get(i) != list.get(list.size() - 1 - i)) 40 | return false; 41 | } 42 | return true; 43 | } 44 | 45 | //为确保不越界,翻转一半看和另一半是否一致 time: O(log_10 n) 46 | public boolean isPalindrome_2(int x) { 47 | if (x < 0 || (x % 10 == 0 && x != 0)) return false; 48 | int reverse_half = 0; //后半段反转的结果 49 | while (reverse_half < x) { //超过一半或者相等时停止 50 | reverse_half = reverse_half * 10 + x % 10; 51 | x /= 10; 52 | } 53 | //偶数位正好相等,奇数位时/10 54 | return (x == reverse_half) || (x == reverse_half / 10); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/offer/_03SearchIn2dArray.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | //@formatter:off 4 | /** 5 | * _ooOoo_ 6 | * o8888888o 7 | * 88" . "88 8 | * (| -_- |) 9 | * O\ = /O 10 | * ____/`---'\____ 11 | * .' \\| |// `. 12 | * / \\||| : |||// \ 13 | * / _||||| -:- |||||- \ 14 | * | | \\\ - /// | | 15 | * | \_| ''\---/'' | | 16 | * \ .-\__ `-` ___/-. / 17 | * ___`. .' /--.--\ `. . __ 18 | * ."" '< `.___\_<|>_/___.' >'"". 19 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 20 | * \ \ `-. \_ __\ /__ _/ .-` / / 21 | * ======`-.____`-.___\_____/___.-`____.-'====== 22 | * `=---=' 23 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 | * 佛祖保佑 永无BUG 25 | * 26 | * 描述:一个二维数组,左到右、上到下递增,找一个数 27 | */ 28 | //@formatter:on 29 | public class _03SearchIn2dArray { 30 | public boolean Find(int target, int[][] array) { 31 | if (array == null) return false; 32 | int rows = array.length; 33 | int cols = array[0].length; 34 | int x = rows - 1; 35 | int y = 0; 36 | while (x >= 0 && y <= cols - 1) { 37 | if (array[x][y] == target) return true; 38 | else if (target > array[x][y]) y++; 39 | else x--; 40 | } 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/offer/_04ReplaceAllSpace.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | //@formatter:off 4 | /** 5 | * _ooOoo_ 6 | * o8888888o 7 | * 88" . "88 8 | * (| -_- |) 9 | * O\ = /O 10 | * ____/`---'\____ 11 | * .' \\| |// `. 12 | * / \\||| : |||// \ 13 | * / _||||| -:- |||||- \ 14 | * | | \\\ - /// | | 15 | * | \_| ''\---/'' | | 16 | * \ .-\__ `-` ___/-. / 17 | * ___`. .' /--.--\ `. . __ 18 | * ."" '< `.___\_<|>_/___.' >'"". 19 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 20 | * \ \ `-. \_ __\ /__ _/ .-` / / 21 | * ======`-.____`-.___\_____/___.-`____.-'====== 22 | * `=---=' 23 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 | * 佛祖保佑 永无BUG 25 | * 26 | * 描述:替换字符串中所有的空格位%20 使用场景:socket传输编码问题 27 | */ 28 | //@formatter:on 29 | public class _04ReplaceAllSpace { 30 | public String replaceSpace(StringBuffer str) { 31 | int spaceNum = 0; 32 | for (int i = 0; i < str.length(); i++) { 33 | if (str.charAt(i) == ' ') spaceNum++;//找到所有的空格 34 | } 35 | str.setLength(str.length() + 2 * spaceNum); 36 | int p = str.length() - 1;//始终指向复制后的头位置 37 | for (int i = str.length() - 2 * spaceNum - 1; i >= 0; i--) { 38 | if (str.charAt(i) != ' ') { 39 | str.setCharAt(p, str.charAt(i)); 40 | p--; 41 | } else { 42 | str.setCharAt(p--, '0'); 43 | str.setCharAt(p--, '2'); 44 | str.setCharAt(p--, '%'); 45 | } 46 | } 47 | return str.toString(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/offer/_05PrintListTailToHead_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | import java.util.ArrayList; 4 | 5 | 6 | //@formatter:off 7 | /** 8 | * _ooOoo_ 9 | * o8888888o 10 | * 88" . "88 11 | * (| -_- |) 12 | * O\ = /O 13 | * ____/`---'\____ 14 | * .' \\| |// `. 15 | * / \\||| : |||// \ 16 | * / _||||| -:- |||||- \ 17 | * | | \\\ - /// | | 18 | * | \_| ''\---/'' | | 19 | * \ .-\__ `-` ___/-. / 20 | * ___`. .' /--.--\ `. . __ 21 | * ."" '< `.___\_<|>_/___.' >'"". 22 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 23 | * \ \ `-. \_ __\ /__ _/ .-` / / 24 | * ======`-.____`-.___\_____/___.-`____.-'====== 25 | * `=---=' 26 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 27 | * 佛祖保佑 永无BUG 28 | * 29 | * 描述:从尾到头打印链表节点值 只读操作 使用递归 30 | */ 31 | //@formatter:on 32 | public class _05PrintListTailToHead_2 { 33 | ArrayList list = new ArrayList<>(); 34 | 35 | 36 | public ArrayList printListFromTailToHead(ListNode listNode) { 37 | if (listNode != null) { 38 | printListFromTailToHead(listNode.next); 39 | list.add(listNode.val); 40 | } 41 | return list; 42 | } 43 | 44 | public static void main(String[] args) { 45 | ListNode node1 = new ListNode(1); 46 | ListNode node2 = new ListNode(2); 47 | ListNode node3 = new ListNode(3); 48 | ListNode node4 = new ListNode(4); 49 | node1.next = node2; 50 | node2.next = node3; 51 | node3.next = node4; 52 | node4.next = null; 53 | _05PrintListTailToHead_2 one = new _05PrintListTailToHead_2(); 54 | ArrayList list = one.printListFromTailToHead(node1); 55 | System.out.println(list); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/offer/_06ReConstructBinaryTree.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | //@formatter:off 4 | /** 5 | * _ooOoo_ 6 | * o8888888o 7 | * 88" . "88 8 | * (| -_- |) 9 | * O\ = /O 10 | * ____/`---'\____ 11 | * .' \\| |// `. 12 | * / \\||| : |||// \ 13 | * / _||||| -:- |||||- \ 14 | * | | \\\ - /// | | 15 | * | \_| ''\---/'' | | 16 | * \ .-\__ `-` ___/-. / 17 | * ___`. .' /--.--\ `. . __ 18 | * ."" '< `.___\_<|>_/___.' >'"". 19 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 20 | * \ \ `-. \_ __\ /__ _/ .-` / / 21 | * ======`-.____`-.___\_____/___.-`____.-'====== 22 | * `=---=' 23 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 | * 佛祖保佑 永无BUG 25 | * 26 | * 描述:输入前序遍历和中序遍历,不含重复数字,重建二叉树 27 | */ 28 | //@formatter:on 29 | public class _06ReConstructBinaryTree { 30 | public TreeNode reConstructBinaryTree(int[] pre, int[] in) { 31 | return reConstruct(pre, 0, pre.length - 1, in, 0, in.length - 1); 32 | } 33 | 34 | private TreeNode reConstruct(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) { 35 | if (startPre > endPre || startIn > endIn) 36 | return null; 37 | TreeNode treeNode = new TreeNode(pre[startPre]); 38 | for (int i = startIn; i <= endIn; i++) { 39 | if (in[i] == pre[startPre]) { 40 | treeNode.left = reConstruct(pre, startPre + 1, startPre + i - startIn, in, startIn, i - 1); 41 | treeNode.right = reConstruct(pre, startPre + i - startIn + 1, endPre, in, i + 1, endIn); 42 | break; 43 | } 44 | } 45 | 46 | return treeNode; 47 | } 48 | } 49 | 50 | class TreeNode { 51 | int val; 52 | TreeNode left; 53 | TreeNode right; 54 | 55 | TreeNode(int x) { 56 | val = x; 57 | } 58 | } -------------------------------------------------------------------------------- /src/offer/_07StackImplementsQueue.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:两个栈实现一个队列 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.Stack; 30 | 31 | public class _07StackImplementsQueue { 32 | Stack stack1 = new Stack(); 33 | Stack stack2 = new Stack(); 34 | 35 | public void push(int node) { 36 | stack1.push(node); 37 | } 38 | 39 | public int pop() { 40 | if (stack2.size() != 0) { 41 | return stack2.pop(); 42 | } else { 43 | while (stack1.size() != 0) {//把1中所有的元素都弹出并推入2中 44 | stack2.push(stack1.pop()); 45 | } 46 | return stack2.pop(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/offer/_08MinNumberInRotatedArray_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:非递减旋转数组中的最小数字 如{3,4,5,1,2}中找到最小的数字1 26 | */ 27 | //@formatter:on 28 | public class _08MinNumberInRotatedArray_2 { 29 | public static int minNumberInRotateArray(int[] array) { 30 | int low = 0; 31 | int high = array.length - 1; 32 | while (low < high) { 33 | int mid = low + (high - low) / 2; 34 | if (array[mid] > array[high]) { 35 | low = mid + 1; 36 | } else if (array[mid] == array[high]) { 37 | high = high - 1; 38 | } else { 39 | high = mid; 40 | } 41 | } 42 | return array[low]; 43 | } 44 | 45 | public static void main(String[] args) { 46 | int[] array = {1, 1, 1, 1, 1, 1, 0, 1, 1}; 47 | int i = _08MinNumberInRotatedArray_2.minNumberInRotateArray(array); 48 | System.out.println(i); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/offer/_09Fibonacci.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一个整数n,输出fibonacci的第n项 使用递归实现 26 | */ 27 | //@formatter:on 28 | public class _09Fibonacci { 29 | public int Fibonacci(int n) { 30 | if (n == 0) return 0; 31 | if (n == 1) return 1; 32 | return Fibonacci(n - 2) + Fibonacci(n - 1); 33 | } 34 | 35 | public static void main(String[] args) { 36 | _09Fibonacci instance = new _09Fibonacci(); 37 | int i = instance.Fibonacci(5); 38 | System.out.println(i); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/offer/_09Fibonacci_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一个整数n,输出fibonacci的第n项 把中间项存起来,减少每次重复计算的开销 迭代 26 | */ 27 | //@formatter:on 28 | public class _09Fibonacci_2 { 29 | public int Fibonacci(int n) { 30 | if (n <= 1) return n; 31 | int firstNum = 0; 32 | int secondNum = 1; 33 | int thirdNum = 0; 34 | for (int i = 2; i <= n; i++) { 35 | thirdNum = firstNum + secondNum; 36 | firstNum = secondNum; 37 | secondNum = thirdNum; 38 | } 39 | 40 | return thirdNum; 41 | } 42 | 43 | public static void main(String[] args) { 44 | _09Fibonacci_2 instance = new _09Fibonacci_2(); 45 | int i = instance.Fibonacci(5); 46 | System.out.println(i); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/offer/_09JumpFloor.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:跳台阶,一次可以跳1个或两个台阶,n个台阶有几种跳法。 f(n) = f(n-1) + f(n-2) 26 | */ 27 | //@formatter:on 28 | public class _09JumpFloor { 29 | public int JumpFloor(int target) { 30 | if (target <= 2) 31 | return target; 32 | int first = 1; 33 | int second = 2; 34 | int third = 0; 35 | for (int i = 3; i <= target; i++) { 36 | third = first + second; 37 | first = second; 38 | second = third; 39 | } 40 | return third; 41 | } 42 | 43 | public int JumpFloor_2(int target) { 44 | if (target <= 2) 45 | return target; 46 | return JumpFloor_2(target - 1) + JumpFloor_2(target - 2); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/offer/_09JumpFloorII.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:一只青蛙跳n个台阶,每一次都可以跳1到n级。供n级台阶有几种跳法 26 | */ 27 | //@formatter:on 28 | public class _09JumpFloorII { 29 | public int JumpFloorII(int target) { 30 | if (target == 1) return 1; 31 | int first = 1; 32 | int second = 0; 33 | for (int i = 2; i <= target; i++) { 34 | second = 2 * first; 35 | first = second; 36 | } 37 | return second; 38 | } 39 | } 40 | 41 | //一次跳1级,则剩下的有f(n-1);一次跳2级,则剩下的有f(n-2)... 42 | //f(n) = f(n-1)+f(n-2)+...+f(1)+1 43 | //f(n-1) = f(n-2)+f(n-3)+...+f(1)+1 44 | //f(n) = 2*f(n-1) 45 | -------------------------------------------------------------------------------- /src/offer/_09RectCover.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 26 | */ 27 | //@formatter:on 28 | public class _09RectCover { 29 | public int RectCover(int target) { 30 | if (target <= 2) 31 | return target; 32 | return RectCover(target - 1) + RectCover(target - 2); 33 | } 34 | } 35 | 36 | // 假设我们横着放,则还剩f(n-1) 37 | // 假设我们竖着靠左放,则右边只能竖着再放一个,则还剩f(n-2) 38 | // f(n) = f(n-1) + f(n-2) Fibonacci 39 | // 这里用了递归的方法,当然也可以用迭代 -------------------------------------------------------------------------------- /src/offer/_10NumberOf1.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 26 | */ 27 | //@formatter:on 28 | public class _10NumberOf1 { 29 | //此法不行,当传入一个负数时,因为右移时,最高位设为1,如果一直做右移运算,最终这个数字变成0xFFFFFFFF而陷入死循环 二进制表示为11111111 11111111 11111111 11111111 其十进制为-1(负数用补码表示:1的反码+1) 30 | public int NumberOf1_1(int n) { 31 | int count = 0; 32 | while (n != 0) { 33 | if ((n & 1) == 1) count++; 34 | n = n >> 1; 35 | } 36 | return count; 37 | } 38 | 39 | //用1先按位与,然后不断左移,进行按位与操作 40 | public int NumberOf1_2(int n) { 41 | int count = 0; 42 | int flag = 1;//00000000 00000000 00000000 00000001 43 | while (flag != 0) {//flag一直左移(int占了四个字节即32位),当最左边1超出边界,则flag = 0 44 | if ((n & flag) != 0) count++; 45 | flag = flag << 1; 46 | } 47 | return count; 48 | } 49 | 50 | //最好的方法 51 | //把一个整数和它减去1的结果做位与运算,相当于把该数最右边的1变成0 52 | public int NumberOf1_3(int n) { 53 | int count = 0; 54 | while (n != 0) { 55 | count++; 56 | n = n & (n - 1); 57 | } 58 | return count; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/offer/_11Power.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 26 | */ 27 | //@formatter:on 28 | public class _11Power { 29 | //累乘 30 | public double Power(double base, int exponent) { 31 | double result = 1.0; 32 | if (base == 0) { 33 | if (exponent == 0) return 1; 34 | else return 0; 35 | } 36 | int absExponent = 0; 37 | if (exponent == 0) return 1; 38 | else if (exponent < 0) absExponent = -exponent;//考虑指数为负时,使用绝对值 39 | else absExponent = exponent; 40 | for (int i = 1; i <= absExponent; i++) { 41 | result *= base; 42 | } 43 | if (exponent < 0) result = 1.0 / result; 44 | 45 | return result; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/offer/_14reOrderArray.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。 26 | */ 27 | //@formatter:on 28 | public class _14reOrderArray { 29 | //用空间换时间,时间复杂度为o(n) 30 | public void reOrderArray(int[] array) { 31 | int length = array.length; 32 | int[] array_new = new int[length]; 33 | int j = 0;//新数组的下标 34 | //将奇数存入新数组 35 | for (int i = 0; i < length; i++) { 36 | if ((array[i] & 1) == 1) {//奇数 37 | array_new[j] = array[i]; 38 | j++; 39 | } 40 | } 41 | //将偶数放入新数组(奇数后面) 42 | for (int i = 0; i < length; i++) { 43 | if ((array[i] & 1) == 0) {//奇数 44 | array_new[j] = array[i]; 45 | j++; 46 | } 47 | } 48 | for (int i = 0; i < length; i++) { 49 | array[i] = array_new[i]; 50 | } 51 | } 52 | 53 | //若不能另辟空间,则可以使用冒泡的思想,从后往前移动,此时空间复杂度较高O(n^2) 54 | } 55 | -------------------------------------------------------------------------------- /src/offer/_16ReverseList.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一个链表,反转链表后,输出链表的所有元素。 26 | */ 27 | //@formatter:on 28 | public class _16ReverseList { 29 | public ListNode ReverseList(ListNode head) { 30 | if (head == null || head.next == null) 31 | return head; 32 | ListNode pre = null; 33 | ListNode p = head; 34 | ListNode post = p.next; 35 | while (post != null) { 36 | //当前节点指向前一个节点 37 | p.next = pre; 38 | //依次更新移动标记指针 39 | pre = p; 40 | p = post; 41 | post = post.next; 42 | } 43 | //最后一个节点指向前面 44 | p.next = pre; 45 | return p; 46 | } 47 | 48 | //将上述代码进行优化,思路一样 49 | public ListNode ReverseList_1(ListNode head) { 50 | if (head == null || head.next == null) 51 | return head; 52 | ListNode p = head; 53 | ListNode pre = null; 54 | ListNode post = null; 55 | while (p != null) { 56 | post = p.next; 57 | p.next = pre; 58 | pre = p; 59 | p = post; 60 | } 61 | return pre; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/offer/_17Merge_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 26 | */ 27 | //@formatter:on 28 | public class _17Merge_2 { 29 | //第二种方法,使用递归的思想 30 | public ListNode Merge(ListNode list1, ListNode list2) { 31 | if (list1 == null) 32 | return list2; 33 | else if (list2 == null) 34 | return list1; 35 | ListNode head = null; 36 | if (list1.val <= list2.val) { 37 | head = list1; 38 | head.next = Merge(list1.next, list2); 39 | } else { 40 | head = list2; 41 | head.next = Merge(list1, list2.next); 42 | } 43 | return head; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/offer/_18HasSubtree.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构) 26 | */ 27 | //@formatter:on 28 | public class _18HasSubtree { 29 | //使用递归的思想 30 | public boolean HasSubtree(TreeNode root1, TreeNode root2) { 31 | boolean result = false; 32 | if (root1 != null && root2 != null) { 33 | if (root1.val == root2.val) //找到1树中和2树的根节点相等的起始节点 34 | result = doesTree1HasTree2(root1, root2);//只要出现不同节点立刻返回false 35 | if (!result)//表示当前节点不等于2树中的根节点 36 | result = HasSubtree(root1.left, root2); 37 | if (!result) 38 | result = HasSubtree(root1.right, root2); 39 | //到这里,可能找了一圈都没找到和2树根节点相等的节点;也可能找到并执行完了doesTree1HasTree2 40 | } 41 | return result; 42 | } 43 | 44 | private boolean doesTree1HasTree2(TreeNode root1, TreeNode root2) { 45 | if (root2 == null) 46 | return true; 47 | if (root1 == null) 48 | return false; 49 | if (root1.val != root2.val) 50 | return false; 51 | //递归判断左右是否相等 52 | return doesTree1HasTree2(root1.left, root2.left) && doesTree1HasTree2(root1.right, root2.right); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/offer/_19Mirror.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:操作给定的二叉树,将其变换为源二叉树的镜像。 26 | */ 27 | //@formatter:on 28 | public class _19Mirror { 29 | public void Mirror(TreeNode root) { 30 | if (root == null || (root.right == null && root.left == null)) 31 | return; 32 | TreeNode temp = root.left; 33 | root.left = root.right; 34 | root.right = temp; 35 | 36 | Mirror(root.left); 37 | Mirror(root.right); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/offer/_21stack.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。时间复杂度都是O(1) 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.Stack; 30 | 31 | public class _21stack { 32 | //思路:用一个辅助栈存放最小值 33 | Stack dataStack = new Stack<>(); 34 | Stack minStack = new Stack<>(); 35 | //标记最小值 36 | Integer min = null; 37 | 38 | public void push(int node) { 39 | dataStack.push(node); 40 | if (min == null || min >= node) { 41 | minStack.push(node); 42 | min = node;//update min value 43 | } 44 | } 45 | 46 | public void pop() { 47 | Integer temp = dataStack.pop(); 48 | if (temp == minStack.peek()) { 49 | minStack.pop(); 50 | min = minStack.peek();//update min value 51 | } 52 | } 53 | 54 | public int top() { 55 | return dataStack.peek(); 56 | } 57 | 58 | public int min() { 59 | return min; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/offer/_22IsPopOrder.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。 26 | * 假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序, 27 | * 序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。 28 | * (注意:这两个序列的长度是相等的) 29 | */ 30 | //@formatter:on 31 | 32 | import java.util.Stack; 33 | 34 | //将pushA逐个压入栈,当popA指向的元素和栈顶元素相同时,将栈顶元素弹出,若最后能完全弹出,则说明true 35 | public class _22IsPopOrder { 36 | public boolean IsPopOrder(int[] pushA, int[] popA) { 37 | if (pushA.length == 0 || popA.length == 0) 38 | return false; 39 | Stack stack = new Stack<>(); 40 | int popIndex = 0; 41 | for (int i = 0; i < pushA.length; i++) { 42 | stack.push(pushA[i]); 43 | //满足以下条件则弹出一个元素 44 | while (!stack.isEmpty() && stack.peek() == popA[popIndex]) { 45 | stack.pop(); 46 | popIndex++; 47 | } 48 | } 49 | return stack.isEmpty(); 50 | } 51 | 52 | public static void main(String[] args) { 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/offer/_23PrintFromTopToBottom.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.ArrayList; 30 | import java.util.Deque; 31 | import java.util.LinkedList; 32 | 33 | //用队列,当一个节点打印出来(即出队的时候)它的左右节点入队 34 | public class _23PrintFromTopToBottom { 35 | public ArrayList PrintFromTopToBottom(TreeNode root) { 36 | ArrayList result = new ArrayList<>(); 37 | if (root == null) return result; 38 | Deque queue = new LinkedList<>(); 39 | queue.add(root); 40 | while (!queue.isEmpty()) { 41 | TreeNode node = queue.poll(); 42 | result.add(node.val); 43 | if (node.left != null) 44 | queue.add(node.left); 45 | if (node.right != null) 46 | queue.add(node.right); 47 | } 48 | return result; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/offer/_24VerifySquenceOfBST.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。 26 | * 如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。 27 | */ 28 | //@formatter:on 29 | public class _24VerifySquenceOfBST { 30 | public boolean VerifySquenceOfBST(int[] sequence) { 31 | if (sequence == null || sequence.length == 0) return false; 32 | return verify(sequence, 0, sequence.length - 1); 33 | } 34 | 35 | private boolean verify(int[] sequence, int start, int end) { 36 | int root = sequence[end]; 37 | int i = start;//遍历sequence的指针 38 | //左子树的结点小于根结点 39 | while (sequence[i] < root) { 40 | i++; 41 | } 42 | //右子树结点大于根结点 43 | for (; i < end; i++) { 44 | if (sequence[i] < root) { 45 | return false; 46 | } 47 | } 48 | boolean left = true; 49 | if (i > start) 50 | left = verify(sequence, start, i - 1); 51 | boolean right = true; 52 | if (i < end) 53 | right = verify(sequence, i, end - 1); 54 | 55 | return left && right; 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/offer/_25FindPath.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 26 | * 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 27 | */ 28 | //@formatter:on 29 | 30 | import java.util.ArrayList; 31 | 32 | public class _25FindPath { 33 | //只有前序遍历是首先打印根节点的 DFS深度优先搜索 34 | private ArrayList> listAll = new ArrayList<>(); 35 | private ArrayList list = new ArrayList<>(); 36 | private int sum = 0; 37 | 38 | public ArrayList> FindPath(TreeNode root, int target) { 39 | //to do boundary 40 | if (root == null) return listAll; 41 | list.add(root.val); 42 | sum += root.val; 43 | if (sum == target && root.left == null && root.right == null) 44 | listAll.add(new ArrayList<>(list));//这里需要重新new,不然所有的元素都是指向同一个list! 45 | FindPath(root.left, target); 46 | FindPath(root.right, target); 47 | list.remove(list.size() - 1); 48 | sum -= root.val; 49 | return listAll; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/offer/_25FindPath_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 26 | * 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 27 | */ 28 | //@formatter:on 29 | 30 | import java.util.ArrayList; 31 | 32 | public class _25FindPath_2 { 33 | //跟解法1思路相同,不同的是这里不使用sum这个全局变量,而是改用target减的方法,较难理解,因为target是栈空间元素,局部变量,所以这里不需要再后面加回退时候的值 34 | private ArrayList> listAll = new ArrayList>(); 35 | private ArrayList list = new ArrayList(); 36 | 37 | public ArrayList> FindPath(TreeNode root, int target) { 38 | if (root == null) return listAll; 39 | list.add(root.val); 40 | target -= root.val; 41 | if (target == 0 && root.left == null && root.right == null) 42 | listAll.add(new ArrayList(list)); 43 | FindPath(root.left, target); 44 | FindPath(root.right, target); 45 | list.remove(list.size() - 1); 46 | return listAll; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/offer/_27Convert.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 26 | * 要求不能创建任何新的结点,只能调整树中结点指针的指向。 27 | */ 28 | //@formatter:on 29 | public class _27Convert { 30 | private class TreeNode { 31 | int val = 0; 32 | TreeNode left = null; 33 | TreeNode right = null; 34 | 35 | public TreeNode(int val) { 36 | this.val = val; 37 | } 38 | } 39 | 40 | //思想:递归 中序遍历 41 | //用一个指针指向链表第一个元素,用另一个指针通过中序遍历往后遍历 42 | private TreeNode head = null; 43 | private TreeNode pNode = null; 44 | 45 | public TreeNode Convert(TreeNode pRootOfTree) { 46 | if (pRootOfTree == null) return null; 47 | Convert(pRootOfTree.left); 48 | if (head == null) { 49 | head = pNode = pRootOfTree;//在最左边这个节点的时候,标记链表head,并将pNode指向第一个节点 50 | } else { 51 | //设置双向指向 52 | pNode.right = pRootOfTree; 53 | pRootOfTree.left = pNode; 54 | pNode = pRootOfTree;//遍历的指针往后移动一位 55 | } 56 | Convert(pRootOfTree.right); 57 | return head; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/offer/_29MoreThanHalfNum_Solution_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 26 | * 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。 27 | * 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 28 | */ 29 | //@formatter:on 30 | 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | 34 | public class _29MoreThanHalfNum_Solution_2 { 35 | /** 36 | * HashMap 37 | */ 38 | public int MoreThanHalfNum_Solution(int[] array) { 39 | if (array == null || array.length == 0) return 0; 40 | int count = 0; 41 | int data = 0; 42 | Map map = new HashMap<>();//key:数字 val:个数 43 | for (int i = 0; i < array.length; i++) { 44 | if (map.get(array[i]) == null) 45 | map.put(array[i], 1); 46 | else { 47 | map.put(array[i], map.get(array[i]) + 1); 48 | } 49 | if (map.get(array[i]) > count) { 50 | count = map.get(array[i]); 51 | data = array[i]; 52 | } 53 | } 54 | if (count * 2 > array.length) 55 | return data; 56 | else return 0; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/offer/_29MoreThanHalfNum_Solution_3.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 26 | * 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。 27 | * 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 28 | */ 29 | //@formatter:on 30 | 31 | import java.util.ArrayList; 32 | import java.util.Collections; 33 | import java.util.List; 34 | 35 | public class _29MoreThanHalfNum_Solution_3 { 36 | /** 37 | * 排序后,只有中间那个数可能符合条件 38 | */ 39 | public int MoreThanHalfNum_Solution(int[] array) { 40 | List list = new ArrayList<>(); 41 | for (int i = 0; i < array.length; i++) { 42 | list.add(array[i]); 43 | } 44 | Collections.sort(list); 45 | int middle = list.get(list.size() / 2);//中间那个数 46 | int count = 0; 47 | for (int data : list) { 48 | if (data == middle) 49 | count++; 50 | } 51 | if (count * 2 > array.length) 52 | return middle; 53 | else return 0; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/offer/_30GetLeastNumbers_Solution.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.ArrayList; 30 | import java.util.Collections; 31 | 32 | public class _30GetLeastNumbers_Solution { 33 | //简单粗暴的全排列,时间复杂度为O(nlogn) 34 | public ArrayList GetLeastNumbers_Solution(int[] input, int k) { 35 | ArrayList list = new ArrayList<>(); 36 | if (input == null || input.length <= 0 || k == 0 || k > input.length) return list; 37 | for (int i = 0; i < input.length; i++) 38 | list.add(input[i]); 39 | Collections.sort(list); 40 | for (int i = list.size() - 1; i >= k; i--) 41 | list.remove(i); 42 | return list; 43 | } 44 | 45 | public static void main(String[] args) { 46 | int[] input = {4, 5, 1, 6, 2, 7, 3, 8}; 47 | int k = 4; 48 | _30GetLeastNumbers_Solution instance = new _30GetLeastNumbers_Solution(); 49 | ArrayList list = instance.GetLeastNumbers_Solution(input, k); 50 | System.out.println(list); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/offer/_31FindGreatestSumOfSubArray.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:连续子数组的最大和例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。 26 | * 要求时间复杂度为O(n) 27 | */ 28 | //@formatter:on 29 | public class _31FindGreatestSumOfSubArray { 30 | //动态规划 31 | public int FindGreatestSumOfSubArray(int[] array) { 32 | if (array == null || array.length <= 0) return 0; 33 | int sum = 0; 34 | int max = Integer.MIN_VALUE; 35 | for (int i = 0; i < array.length; i++) { 36 | if (sum <= 0)//若前面的几个数部分和小于0,则此时的数加上他肯定变小,所以sum变成此时这个数;前面的max已保存 37 | sum = array[i]; 38 | else 39 | sum += array[i]; 40 | if (sum > max) //更新max值 41 | max = sum; 42 | } 43 | return max; 44 | } 45 | 46 | public static void main(String[] args) { 47 | int[] array = {1, -2, 3, 10, -4, 7, 2, -5}; 48 | //int[] array = {-2, -8, -1, -5, -9}; 49 | _31FindGreatestSumOfSubArray instance = new _31FindGreatestSumOfSubArray(); 50 | int max = instance.FindGreatestSumOfSubArray(array); 51 | System.out.println(max); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/offer/_33PrintMinNumber.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | public class _33PrintMinNumber { 7 | public String PrintMinNumber(int[] numbers) { 8 | if (numbers == null || numbers.length <= 0) return ""; 9 | String[] strs = new String[numbers.length]; 10 | for (int i = 0; i < numbers.length; i++)//转化为String数组 11 | strs[i] = String.valueOf(numbers[i]); 12 | Arrays.sort(strs, new Comparator() { 13 | @Override 14 | public int compare(String s1, String s2) { 15 | String c1 = s1 + s2; 16 | String c2 = s2 + s1; 17 | return c1.compareTo(c2);//谁小放前面,比的是拼接的,放的是原来的s1和s2 18 | } 19 | }); 20 | StringBuilder sb = new StringBuilder(); 21 | for (int i = 0; i < strs.length; i++) { 22 | sb.append(strs[i]); 23 | } 24 | return sb.toString(); 25 | } 26 | } 27 | 28 | //解题思路: 29 | //先将整型数组转换成String数组,然后将String数组排序,最后将排好序的字符串数组拼接出来。关键就是制定排序规则。 30 | //排序规则如下: 31 | //若ab > ba 则 TrieTree > b, 32 | //若ab < ba 则 TrieTree < b, 33 | //若ab = ba 则 TrieTree = b; 34 | //解释说明: 35 | //比如 "3" < "31"但是 "331" > "313",所以要将二者拼接起来进行比较 -------------------------------------------------------------------------------- /src/offer/_35FirstNotRepeatingChar.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.HashMap; 30 | import java.util.Map; 31 | 32 | public class _35FirstNotRepeatingChar { 33 | public int FirstNotRepeatingChar(String str) { 34 | if (str == null || str.length() <= 0) return -1; 35 | Map map = new HashMap<>();//用来记录每个数字出现的次数 36 | for (int i = 0; i < str.length(); i++) { 37 | char data = str.charAt(i); 38 | if (map.get(data) == null) 39 | map.put(data, 1); 40 | else 41 | map.put(data, map.get(data) + 1); 42 | } 43 | int result = -1; 44 | for (int i = 0; i < str.length(); i++) { 45 | if (map.get(str.charAt(i)) == 1) { 46 | result = i; 47 | break; 48 | } 49 | } 50 | return result; 51 | } 52 | 53 | public static void main(String[] args) { 54 | String str = "google"; 55 | _35FirstNotRepeatingChar instance = new _35FirstNotRepeatingChar(); 56 | int i = instance.FirstNotRepeatingChar(str); 57 | System.out.println(i); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/offer/_37FindFirstCommonNode.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入两个链表,找出它们的第一个公共结点 26 | */ 27 | //@formatter:on 28 | public class _37FindFirstCommonNode { 29 | public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { 30 | if (pHead1 == null || pHead2 == null) return null; 31 | int len1 = getLength(pHead1); 32 | int len2 = getLength(pHead2); 33 | int step = len1 - len2; 34 | ListNode pLong = pHead1; 35 | ListNode pShort = pHead2; 36 | if (step < 0) { 37 | pLong = pHead2; 38 | pShort = pHead1; 39 | step = -step; 40 | } 41 | for (int i = 0; i < step; i++) 42 | pLong = pLong.next; 43 | //到这里两个指针处在同一起跑线上,即后面的节点数量相同 44 | while (pLong != null && pShort != null && pLong != pShort) { 45 | pLong = pLong.next; 46 | pShort = pShort.next; 47 | } 48 | //相等即调出循环,到末尾没有公共节点也跳出循环 49 | return pLong; 50 | 51 | } 52 | 53 | //获得链表长度 54 | private int getLength(ListNode head) { 55 | int len = 0; 56 | while (head != null) { 57 | len++; 58 | head = head.next; 59 | } 60 | return len; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/offer/_39IsBalanced.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。任意节点左右子树的深度不超过1 26 | */ 27 | //@formatter:on 28 | public class _39IsBalanced { 29 | //此方法重复遍历了一个节点 30 | public boolean IsBalanced_Solution(TreeNode root) { 31 | if (root == null) return true; 32 | int left = TreeDepth(root.left); 33 | int right = TreeDepth(root.right); 34 | int diff = left - right; 35 | if (diff > 1 || diff < -1) return false; 36 | return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right); 37 | } 38 | 39 | private int TreeDepth(TreeNode node) { 40 | if (node == null) return 0; 41 | int leftDepth = TreeDepth(node.left); 42 | int rightDepth = TreeDepth(node.right); 43 | return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/offer/_39IsBalanced_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。任意节点左右子树的深度不超过1 26 | */ 27 | //@formatter:on 28 | public class _39IsBalanced_2 { 29 | //每个节点只遍历一次的解法 后序遍历的时候记录深度 30 | private boolean isBalanced = true; 31 | 32 | public boolean IsBalanced_Solution(TreeNode root) { 33 | getDepth(root); 34 | return isBalanced; 35 | } 36 | 37 | private int getDepth(TreeNode node) { 38 | if (node == null) return 0; 39 | int left = getDepth(node.left); 40 | int right = getDepth(node.right); 41 | if (Math.abs(left - right) > 1)//遍历到这个点的时候,如果他不平衡则设为false 42 | isBalanced = false; 43 | return right > left ? right + 1 : left + 1; 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/offer/_39TreeDepth.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:输入一棵二叉树,求该树的深度。 26 | * 从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。 27 | */ 28 | //@formatter:on 29 | public class _39TreeDepth { 30 | //递归 31 | public int TreeDepth(TreeNode root) { 32 | if (root == null) return 0; 33 | int leftDepth = TreeDepth(root.left); 34 | int rightDepth = TreeDepth(root.right); 35 | return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/offer/_40FindNumsAppearOnce_2.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 26 | */ 27 | //@formatter:on 28 | 29 | public class _40FindNumsAppearOnce_2 { 30 | //时间复杂度为O(n),空间复杂度为O(1) 使用异或:相同为0,相异为1 31 | public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) { 32 | //先异或所有的数 33 | int xorResult = 0; 34 | for (int i = 0; i < array.length; i++) 35 | xorResult ^= array[i]; 36 | //找到二进制第一个1的位置,做为分组条件 37 | int index = findFirst1(xorResult); 38 | for (int i = 0; i < array.length; i++) { 39 | if (isBit1(array[i], index)) 40 | num1[0] ^= array[i]; 41 | else 42 | num2[0] ^= array[i]; 43 | } 44 | } 45 | 46 | private boolean isBit1(int target, int index) { 47 | return ((target >> index) & 1) == 1; 48 | } 49 | 50 | private int findFirst1(int xorResult) { 51 | int index = 0; 52 | while ((xorResult & 1) == 0) { 53 | xorResult >>= 1;//往右移动一位 54 | index++; 55 | } 56 | return index; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/offer/_42LeftRotateString.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。 26 | * 例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。 27 | */ 28 | //@formatter:on 29 | public class _42LeftRotateString { 30 | //思路:将字符串分成两部分,每一部分分别反转,合并后再反转一次 31 | public String LeftRotateString(String str, int n) { 32 | if (str == null || str.length() <= 1) return str; 33 | //处理n 34 | n %= str.length(); 35 | //因为String不可变,转化 36 | char[] chars = str.toCharArray(); 37 | reverse(chars, 0, n - 1); 38 | reverse(chars, n, chars.length - 1); 39 | reverse(chars, 0, chars.length - 1); 40 | return new String(chars); 41 | } 42 | 43 | //反转指定长度位置的内容 44 | private void reverse(char[] chars, int start, int end) { 45 | while (start < end) { 46 | char temp = chars[start]; 47 | chars[start] = chars[end]; 48 | chars[end] = temp; 49 | start++; 50 | end--; 51 | } 52 | } 53 | 54 | public static void main(String[] args) { 55 | _42LeftRotateString instance = new _42LeftRotateString(); 56 | String s = instance.LeftRotateString("123456", 2); 57 | System.out.println(s); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/offer/_42ReverseSentence.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:例如,“student. TrieTree am I”。反转回 “I am TrieTree student.” 26 | */ 27 | //@formatter:on 28 | public class _42ReverseSentence { 29 | //思路:将str完全反转,然后每个再反转 30 | public String ReverseSentence(String str) { 31 | char[] chars = str.toCharArray(); 32 | reverse(chars, 0, chars.length - 1); 33 | 34 | int preHead = -1;//标志每一个段的开头位 35 | for (int i = 0; i < chars.length; i++) { 36 | if (chars[i] == ' ') { 37 | int tail = i; 38 | reverse(chars, preHead + 1, tail - 1); 39 | preHead = tail; 40 | } 41 | } 42 | reverse(chars, preHead + 1, chars.length - 1);//最后一个单词单独进行反转,因为最后没有空格 43 | return new String(chars); 44 | } 45 | 46 | //反转指定长度位置的内容 47 | private void reverse(char[] chars, int start, int end) { 48 | while (start < end) { 49 | char temp = chars[start]; 50 | chars[start] = chars[end]; 51 | chars[end] = temp; 52 | start++; 53 | end--; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/offer/_44isContinuous.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:从扑克牌中随机抽牌,判断是不是一个顺子,1-13,大小王可看成任意数,自定义为0 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.Arrays; 30 | 31 | public class _44isContinuous { 32 | //思路:统计数组中0的个数,统计各个相邻之间的差 与 0的个数比较(若出现重复的数直接返回false) 33 | public boolean isContinuous(int[] numbers) { 34 | if (numbers == null || numbers.length < 1) return false; 35 | //排序 36 | Arrays.sort(numbers); 37 | int numOfZero = 0; 38 | //统计0的个数 39 | for (int i = 0; i < numbers.length; i++) { 40 | if (numbers[i] == 0) 41 | numOfZero++; 42 | } 43 | //比较间隔大小 44 | int gap = 0; 45 | int p = numOfZero;//p要从非0的开始 46 | while (p < numbers.length - 1) { 47 | int q = p + 1; 48 | if (numbers[q] == numbers[p]) return false; 49 | else 50 | gap += numbers[q] - numbers[p] - 1; 51 | p++; 52 | } 53 | return gap - numOfZero == 0 || gap == 0; //若没有间隔也可,不能忘记加上 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/offer/_45LastRemaining.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:0,1,..,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.LinkedList; 30 | 31 | public class _45LastRemaining { 32 | //环形链表 33 | public int LastRemaining_Solution(int n, int m) { 34 | LinkedList list = new LinkedList<>(); 35 | for (int i = 0; i < n; i++) list.add(i); 36 | int del_index = 0; 37 | while (list.size() > 1) { 38 | del_index = (del_index + m - 1) % list.size();//删除环形链表中的第几个元素 39 | list.remove(del_index); 40 | } 41 | return list.size() == 1 ? list.get(0) : -1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/offer/_46Sum.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。 26 | */ 27 | //@formatter:on 28 | public class _46Sum { 29 | //利用逻辑与的短路特性实现递归终止 30 | public int Sum_Solution(int n) { 31 | int sum = n; 32 | boolean flag = (n > 0) && ((sum += Sum_Solution(n - 1)) > 0); 33 | return sum; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/offer/_47Add.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:不用加减乘除做加法 26 | */ 27 | //@formatter:on 28 | public class _47Add { 29 | //异或操作得不算进位的结果,与操作并向左移动一位获得进位 30 | public int Add(int num1, int num2) { 31 | while (num2 != 0) { 32 | int temp = num1 ^ num2; //得到的是不考虑进位的结果 33 | num2 = (num1 & num2) << 1;//进位 34 | num1 = temp; 35 | } 36 | return num1; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/offer/_49StrToInt.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:把字符串转换成整数 26 | */ 27 | //@formatter:on 28 | public class _49StrToInt { 29 | public int StrToInt(String str) { 30 | if (str == null || str.length() == 0) return 0; 31 | char[] chars = str.toCharArray(); 32 | int s = 1;//符号位 33 | int res = 0;//结果 34 | if (chars[0] == '-') s = -1; 35 | for (int i = ((chars[0] == '+' || chars[0] == '-') ? 1 : 0); i < chars.length; i++) {//如果有符号从第二个开始遍历 36 | if (!(chars[i] >= '0' && chars[i] <= '9')) return 0;//如果存在不为数字的值就返回0 37 | res = (res << 1) + (res << 3) + (chars[i] & 0xf);//等同于res=res*10+chars[i]-'0'; res*2 + res*8 38 | //字符'0'到'9'的ascii值的低4个二进制位刚好就是0到9所以chars[i]&0xf等于chars[i]-'0'。 39 | } 40 | return res * s; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/offer/_50duplicate.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 26 | * 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。 27 | */ 28 | //@formatter:on 29 | public class _50duplicate { 30 | //用一个boolean的辅助数组;由于都是小于n的数,可以将其作为下标,相同的数在同一位置,类似于hash的功能 31 | public boolean duplicate(int numbers[], int length, int[] duplication) { 32 | if (numbers == null || numbers.length <= 1) return false; 33 | boolean[] k = new boolean[numbers.length];//初始化后都为false; 34 | for (int i = 0; i < numbers.length; i++) { 35 | if (k[numbers[i]] == true) {//说明前面已经有相同的数了 36 | duplication[0] = numbers[i]; 37 | return true; 38 | } 39 | 40 | k[numbers[i]] = true;//循环到该数,就在对应的boolean数组上设为true 41 | } 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/offer/_51multiply.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1], 26 | * 其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。 27 | */ 28 | //@formatter:on 29 | public class _51multiply { 30 | //一个矩阵把对角线去掉,每一行的乘积就是B对应位置的值,下三角连乘,上三角从后往前连乘,再每行相乘 31 | /* 32 | B0 0 1 1 1 1 33 | B1 1 0 1 1 1 34 | B2 1 1 0 1 1 35 | B3 1 1 1 0 1 36 | B4 1 1 1 1 0 37 | */ 38 | public int[] multiply(int[] A) { 39 | int[] B = new int[A.length]; 40 | //计算下三角 41 | B[0] = 1; 42 | for (int i = 1; i < B.length; i++) 43 | B[i] = B[i - 1] * A[i - 1];//每一行比上一行多乘一个A[i-1] 44 | //再乘上三角(这里最后一行就不动了) 45 | int temp = 1;//这个用来辅助在前面的基础上乘 46 | for (int j = B.length - 2; j >= 0; j--) { 47 | temp *= A[j + 1]; 48 | B[j] *= temp; 49 | } 50 | return B; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/offer/_54FirstAppearingOnce.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。 26 | * 如果当前字符流没有存在出现一次的字符,返回#字符。 27 | */ 28 | //@formatter:on 29 | public class _54FirstAppearingOnce { 30 | //一个字符占8位,因此不会超过256个,可以申请一个256大小的数组来实现一个简易的哈希表。 31 | // 时间复杂度为O(n),空间复杂度O(n). 32 | //一个字符占8bit,所以ascii码表中的字符256个,但只有128是可见的,所以数组大小改为128也没问题。 33 | int[] temp = new int[128]; 34 | StringBuilder s = new StringBuilder(); 35 | 36 | //Insert one char from stringstream 37 | public void Insert(char ch) { 38 | s.append(ch); 39 | temp[ch]++; 40 | 41 | } 42 | 43 | //return the first appearence once char in current stringstream 44 | public char FirstAppearingOnce() { 45 | char[] chars = s.toString().toCharArray(); 46 | for (char c : chars) { 47 | if (temp[c] == 1) 48 | return c; 49 | } 50 | return '#'; 51 | } 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/offer/_55EntryNodeOfLoop.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:一个链表中包含环,请找出该链表的环的入口结点。 26 | */ 27 | //@formatter:on 28 | public class _55EntryNodeOfLoop { 29 | public ListNode EntryNodeOfLoop(ListNode pHead) { 30 | if (pHead == null || pHead.next == null || pHead.next.next == null) return null; 31 | ListNode slow = pHead.next; 32 | ListNode fast = pHead.next.next; 33 | while (slow != fast) { 34 | slow = slow.next; 35 | fast = fast.next.next; 36 | if (slow == null || fast == null) return null;//说明无环,退出 37 | } 38 | //到这里它们相遇了,一个从头开始走,一个从相遇点开始走 39 | slow = pHead; 40 | while (slow != fast) { 41 | slow = slow.next; 42 | fast = fast.next; 43 | } 44 | return fast; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/offer/_56deleteDuplication.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | import java.util.List; /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 26 | * 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 27 | */ 28 | //@formatter:on 29 | public class _56deleteDuplication { 30 | public ListNode deleteDuplication(ListNode pHead) { 31 | ListNode preHead = new ListNode(-1); 32 | preHead.next = pHead; 33 | ListNode pre = preHead;//标记前面一个节点 34 | ListNode compare = pHead;//待比较节点 35 | while (compare != null && compare.next != null) { 36 | if (compare.val == compare.next.val) {//如果和后面一个数相等 37 | int temp = compare.val; 38 | while (compare != null && temp == compare.val) {//只要当前点等于temp即相同的值,compare就往后移动一个 39 | compare = compare.next; 40 | } 41 | pre.next = compare;//pre接上后面的compare 42 | } else {//和后面一个数不等,此时可以移动pre了 43 | pre = compare; 44 | compare = compare.next; 45 | } 46 | 47 | } 48 | 49 | return preHead.next; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/offer/_57GetNext.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。 26 | * 注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。 27 | */ 28 | //@formatter:on 29 | class TreeLinkNode { 30 | int val; 31 | TreeLinkNode left = null; 32 | TreeLinkNode right = null; 33 | TreeLinkNode next = null;//指向父节点的指针 34 | 35 | TreeLinkNode(int val) { 36 | this.val = val; 37 | } 38 | } 39 | 40 | public class _57GetNext { 41 | public TreeLinkNode GetNext(TreeLinkNode pNode) { 42 | if (pNode == null) return null; 43 | //如果有右子树,则找右子树中最左边的节点 44 | if (pNode.right != null) { 45 | pNode = pNode.right;//找到右子树 46 | while (pNode.left != null) 47 | pNode = pNode.left; 48 | return pNode; 49 | } else {//如果没有右子树,找第一个当前节点是父节点左孩子的节点,并输出父节点 50 | while (pNode.next != null) { 51 | if (pNode.next.left == pNode) return pNode.next; 52 | pNode = pNode.next; 53 | } 54 | } 55 | //退到根节点仍未找到,返回null 56 | return null; 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/offer/_58isSymmetrical.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。 26 | */ 27 | //@formatter:on 28 | public class _58isSymmetrical { 29 | boolean isSymmetrical(TreeNode pRoot) { 30 | if (pRoot == null) return true; 31 | return isSymmetricalCore(pRoot.left, pRoot.right); 32 | } 33 | 34 | private boolean isSymmetricalCore(TreeNode left, TreeNode right) { 35 | if (left == null) return right == null;//若右边也等于null,则返回true 36 | if (right == null) return false;//到这步说明left!=null,此时right==null肯定是false 37 | if (left.val != right.val) return false; 38 | return isSymmetricalCore(left.left, right.right) && isSymmetricalCore(left.right, right.left); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/offer/_60Print.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。 26 | */ 27 | //@formatter:on 28 | 29 | import java.util.ArrayList; 30 | import java.util.LinkedList; 31 | 32 | public class _60Print { 33 | ArrayList> Print(TreeNode pRoot) { 34 | ArrayList> result = new ArrayList<>(); 35 | if (pRoot == null) return result; 36 | LinkedList queue = new LinkedList(); 37 | queue.addLast(pRoot); 38 | while (queue.size() != 0) { 39 | //记录当前的值 40 | int lo = 0; 41 | int hi = queue.size() - 1; 42 | ArrayList list = new ArrayList<>(); 43 | while (lo++ <= hi) {//将当前队列里面的元素拿出打印,这样做不需要另外定义分隔符号 44 | TreeNode node = queue.removeFirst();//移除的同时加入它的左右子树 45 | if (node.left != null) queue.addLast(node.left); 46 | if (node.right != null) queue.addLast(node.right); 47 | list.add(node.val); 48 | } 49 | result.add(list); 50 | } 51 | return result; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/offer/_61Serialize.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:请实现两个函数,分别用来序列化和反序列化二叉树 26 | */ 27 | //@formatter:on 28 | public class _61Serialize { 29 | public int index = -1; 30 | 31 | 32 | //只要保持序列化和反序列化规则一样就行 33 | String Serialize(TreeNode root) { 34 | StringBuilder sb = new StringBuilder();//每次递归时产生新的 35 | if (root == null) { 36 | sb.append("#,");//空用#表示 37 | return sb.toString(); 38 | } 39 | //先序遍历 40 | sb.append(root.val + ","); 41 | sb.append(Serialize(root.left));//append上左子树 42 | sb.append(Serialize(root.right)); 43 | return sb.toString(); 44 | } 45 | 46 | TreeNode Deserialize(String str) { 47 | index++;//标记位置,每次递归都会往后走一个成为左右子树 48 | int len = str.length(); 49 | /*if (index >= len) //超过了 50 | return null;*/ 51 | String[] strings = str.split(","); 52 | TreeNode node = null; 53 | if (!strings[index].equals("#")) {//如果不是空格 54 | node = new TreeNode(Integer.valueOf(strings[index])); 55 | node.left = Deserialize(str); 56 | node.right = Deserialize(str); 57 | } 58 | return node; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/offer/_62KthNode.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | //@formatter:off 3 | /** 4 | * _ooOoo_ 5 | * o8888888o 6 | * 88" . "88 7 | * (| -_- |) 8 | * O\ = /O 9 | * ____/`---'\____ 10 | * .' \\| |// `. 11 | * / \\||| : |||// \ 12 | * / _||||| -:- |||||- \ 13 | * | | \\\ - /// | | 14 | * | \_| ''\---/'' | | 15 | * \ .-\__ `-` ___/-. / 16 | * ___`. .' /--.--\ `. . __ 17 | * ."" '< `.___\_<|>_/___.' >'"". 18 | * | | : `- \`.;`\ _ /`;.`/ - ` : | | 19 | * \ \ `-. \_ __\ /__ _/ .-` / / 20 | * ======`-.____`-.___\_____/___.-`____.-'====== 21 | * `=---=' 22 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 23 | * 佛祖保佑 永无BUG 24 | * 25 | * 描述:给定一颗二叉搜索树,请找出其中的第k大的结点。 26 | * 例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。 27 | */ 28 | //@formatter:on 29 | public class _62KthNode { 30 | int index = 0; //计数器 31 | 32 | //中序遍历 33 | TreeNode KthNode(TreeNode pRoot, int k) { 34 | if (pRoot != null) { 35 | TreeNode node = KthNode(pRoot.left, k); 36 | if (node != null) return node; 37 | index++; 38 | if (index == k) return pRoot; 39 | node = KthNode(pRoot.right, k); 40 | if (node != null) return node; 41 | } 42 | return null; 43 | } 44 | } 45 | /* 46 | 如果没有if(node != null)这句话   47 | 那么那个root就是返回给上一级的父结点的,而不是递归结束的条件了,有了这句话过后, 48 | 一旦返回了root,那么node就不会为空了,就一直一层层的递归出去到结束了。 49 | 举第一个例子{8,6,5,7,},1 答案应该是5,如果不加的时候,开始,root=8,node=kth(6,1),继续root=6,node=kth(5,1)root =5 返回null,这时向下执行index=k=1了,返回 5给root=6递归的时候的node,这时回到root=8了,往后面调右孩子的时候为空而把5给覆盖了。现在就为空了,有了这句话后虽然为空,但不把null返回,而是继续返回5 50 | */ -------------------------------------------------------------------------------- /src/simulation/判断字符串由子串复制组成.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 给出一个非空的字符串,判断这个字符串是否是由它的一个子串进行多次首尾拼接构成的。 7 | 例如:abcabcabc满足条件输出子串,而abcab不满足条件输出false 8 | */ 9 | public class 判断字符串由子串复制组成 { 10 | 11 | public static boolean check(String a, String sub) { 12 | int sub_length = sub.length(); 13 | if (a.length() % sub_length != 0) return false; 14 | int epoch = a.length() / sub_length; 15 | for (int i = 0; i < epoch; i++) { 16 | if (!sub.equals(a.substring(sub_length * i, sub_length * i + sub_length))) 17 | return false; 18 | } 19 | return true; 20 | } 21 | 22 | public static void main(String args[]) { 23 | Scanner scan = new Scanner(System.in); 24 | String a = scan.next(); 25 | String result = ""; 26 | boolean flag = false; 27 | for (int i = 0; i < (a.length() / 2); i++) { 28 | String sub = a.substring(0, i + 1); 29 | if (check(a, sub)) { 30 | flag = true; 31 | result = sub; 32 | } 33 | } 34 | System.out.print(flag ? result : "false"); 35 | } 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/simulation/因式分解.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 一个整数N分解为两个整数X和Y相乘,且满足X为奇数,Y为偶数 7 | 输入第一行正整数t(1<=t<=1000),接下来t行,每行一个正整数N(2<=N<2^63) 8 | 如果找到,一次输出X,Y,如果有多解输出Y最小的那组,以空格风格;否则输出No 9 | 2 10 | 10 11 | 5 12 | 13 | 5 2 14 | No 15 | */ 16 | public class 因式分解 { 17 | public static void main(String[] args) { 18 | Scanner sc = new Scanner(System.in); 19 | int t = sc.nextInt(); 20 | long[] N = new long[t]; 21 | for (int i = 0; i < N.length; i++) 22 | N[i] = sc.nextLong(); 23 | for (int i = 0; i < N.length; i++) 24 | findXY(N[i]); 25 | } 26 | 27 | private static void findXY(long N) { 28 | if (N % 2 == 1) 29 | System.out.println("No"); 30 | else { 31 | long X = N; 32 | while (X % 2 == 0) { 33 | X /= 2; 34 | } 35 | long Y = N / X; 36 | System.out.println(X + " " + Y); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/simulation/括号配对所有情况.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | 7 | /* 8 | 给出正整数n,请给出所有的包含n个'('和n个')'的字符串,使得'('和')'可以完全匹配。 9 | 例如:'(())()','()()()'都是合法的。 '())()('不合法 10 | 请按照字典序给出所有合法的字符串 11 | 例如: 12 | 2 13 | (()),()() 14 | */ 15 | public class 括号配对所有情况 { 16 | private static void helper(List res, String curStr, int left, int right) { 17 | if (left == 0 && right == 0) {//说明一种情况结束 18 | res.add(curStr); 19 | } 20 | if (left > 0) { 21 | curStr = curStr + "("; 22 | helper(res, curStr, left - 1, right); 23 | curStr = curStr.substring(0, curStr.length() - 1);//回溯 24 | } 25 | if (right > 0 && right > left) { 26 | curStr = curStr + ")"; 27 | helper(res, curStr, left, right - 1); 28 | } 29 | } 30 | 31 | public static void main(String[] args) { 32 | Scanner sc = new Scanner(System.in); 33 | int n = sc.nextInt(); 34 | List res = new ArrayList<>(); 35 | helper(res, "", n, n);//n个( n个) 36 | for (int i = 0; i < res.size(); i++) { 37 | if (i == res.size() - 1) { 38 | System.out.print(res.get(i)); 39 | } else 40 | System.out.print(res.get(i) + ","); 41 | } 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/simulation/整数划分最大乘积.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 招行信用卡 7 | 给出一个整数n,将n分解为至少两个整数之和,使得这些整数的乘积最大化,输出能够获得的最大的乘积。 8 | 例如: 9 | 2=1+1,输出1 10 | 10=3+3+4,输出36 11 | 10 12 | 36 13 | */ 14 | public class 整数划分最大乘积 { 15 | public static void main(String[] args) { 16 | Scanner sc = new Scanner(System.in); 17 | int num = sc.nextInt(); 18 | if (num % 3 == 0) { 19 | System.out.println((int) (Math.pow(3, num / 3))); 20 | return; 21 | } 22 | if (num % 3 == 1) { 23 | int temp = num / 3 - 1; 24 | System.out.println((int) (Math.pow(3, temp) * 4)); 25 | } 26 | if (num % 3 == 2) { 27 | int temp = num / 3; 28 | System.out.println((int) (Math.pow(3, temp) * 2)); 29 | } 30 | return; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/simulation/最多硬币问题.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | /* 7 | 给定几个数(5) 要求从中选出最多的个数使得他们的和大于给定的值(9) 并且从中减去任何一个数都会比给定值小,返回最多几个数 8 | 9 | 5 9 10 | 1 1 7 2 1 11 | 3 12 | */ 13 | public class 最多硬币问题 { 14 | public static void main(String[] args) { 15 | Scanner sc = new Scanner(System.in); 16 | int count = sc.nextInt();//个数 17 | int total = sc.nextInt();//给定值 18 | int[] coins = new int[count]; 19 | for (int i = 0; i < coins.length; i++) { 20 | coins[i] = sc.nextInt(); 21 | } 22 | Arrays.sort(coins); //排序 23 | int[] sum = new int[coins.length]; //当前的和 24 | sum[0] = coins[0]; 25 | int p = 0; 26 | for (int i = 1; i < coins.length; i++) { 27 | sum[i] = sum[i - 1] + coins[i]; 28 | if (sum[i] >= total) { //加到超过给定的值为止 29 | p = i; 30 | break; 31 | } 32 | } 33 | 34 | int preSum = sum[p]; 35 | for (int i = p; i >= 0; i--) { 36 | if (preSum - coins[i] >= total) { //每一次减去当前位置上的值,如果比给定值大则确定减去 37 | preSum -= coins[i]; 38 | p--; 39 | } 40 | } 41 | System.out.println(p + 1); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/simulation/最小不能表示的数.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | /* 3 | 输入一串由'0'~'9'组成的字符串,从中选取字符组成数字,例如输入112,可以组成11,12,112,211..但不能组成111,100... 4 | 输出最小的不能表示的正整数 5 | 样例: 6 | 55 7 | 1 8 | 样例: 9 | 0123456789 10 | 11 11 | 样例: 12 | 123456789 13 | 10 14 | 样例: 15 | 12346789 16 | 5 17 | 样例: 18 | 9988776554433221100 19 | 66 20 | */ 21 | 22 | import java.util.Scanner; 23 | 24 | //基本思路:哪个数出现的次数最少,那么就在他个数上追加一个自身的数组成最小不能表示的数,0特殊考虑 25 | public class 最小不能表示的数 { 26 | public static void main(String[] args) { 27 | Scanner sc = new Scanner(System.in); 28 | char[] chars = sc.nextLine().toCharArray(); 29 | int[] number = new int[10];//存放每个数字出现的次数,下标对应数字本身 30 | for (char c : chars) { 31 | int i = c - '0'; 32 | number[i]++; 33 | } 34 | /* //查看1-9是否有缺的数,如果就输出这个数 35 | for (int i = 1; i <= 9; i++) { 36 | if (number[i] == 0) { 37 | System.out.println(i); 38 | return; 39 | } 40 | }*/ 41 | //寻找最少的数 42 | int min = 0;//最少数量对应数的下标 43 | for (int i = 0; i <= 9; i++) { 44 | if (number[i] < number[min]) { 45 | min = i; 46 | } 47 | } 48 | if (min == 0) {//说明最少的数是0 49 | for (int i = 1; i <= 9; i++) { 50 | if (number[i] == number[0]) {//数量和0的数量相等 51 | for (int j = 0; j <= number[i]; j++) { 52 | System.out.print(i); 53 | } 54 | return; 55 | } 56 | } 57 | //到这里说明其他数都比0多,最小数为1000... 58 | System.out.print(1); 59 | for (int i = 0; i <= number[0]; i++) { 60 | System.out.print(0); 61 | } 62 | } else {//最少的不是0 63 | for (int k = 0; k <= number[min]; k++) { 64 | System.out.print(min); 65 | } 66 | return; 67 | } 68 | 69 | } 70 | 71 | 72 | private static void print(int[] number) { 73 | for (int i : number) { 74 | System.out.print(i + "\t"); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/simulation/歌单组成方式.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次 7 | 在不考虑歌单内歌曲先后顺序的情况下,请问有多少种组成歌单的方法。 8 | 输入: 9 | 第一行表示歌单的总长度 10 | 接下来的一行包括四个正整数,分别表示歌的第一种长度A(A<=10) 和数量X(X<=100)以及歌的第二种长度B(B<=10) 和数量Y(Y<=100),保证A不等于B 11 | 输出描述: 12 | 输出一个整数,表示组成歌单的方法取模。因为答案可能会很大,输出对1000000007取模的结果 13 | 5 14 | 2 3 3 3 15 | 16 | 9 17 | */ 18 | public class 歌单组成方式 { 19 | public static void main(String[] args) { 20 | Scanner sc = new Scanner(System.in); 21 | int K = sc.nextInt();//歌单长度为K 22 | int A = sc.nextInt();//A长度的歌,每首歌都不同 23 | int X = sc.nextInt();//X首 24 | int B = sc.nextInt();//B长度的歌,... 25 | int Y = sc.nextInt();//Y首 26 | 27 | int[][] dp = new int[X + Y + 1][K + 1]; //6首歌曲长度为5的方法数,为了数字对应行列都加1 28 | //i首歌曲,组成长度为0的方法数 = 1 29 | for (int row = 0; row < X + Y + 1; row++) 30 | dp[row][0] = 1; 31 | for (int i = 1; i < X + Y + 1; i++) { // i是歌曲数 32 | for (int j = 1; j < K + 1; j++) { //j是长度 33 | if (i <= X) { 34 | if (j - A >= 0) 35 | dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - A]) % 1000000007; 36 | else 37 | dp[i][j] = dp[i - 1][j] % 1000000007; 38 | } else if (i <= X + Y) { 39 | if (j - B >= 0) 40 | dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - B]) % 1000000007; 41 | else 42 | dp[i][j] = dp[i - 1][j] % 1000000007; 43 | } 44 | } 45 | } 46 | System.out.println(dp[X + Y][K]); 47 | } 48 | } 49 | /* 50 | 6首歌组成5的方法 = 5首歌组成5的方法 + 5首歌组成(5-一首歌长度)的方法 51 | (这个加上一首歌正好可以组成6首歌) 52 | 或者: 53 | 6首歌组成5的方法 = 5首歌组成5的方法 54 | */ -------------------------------------------------------------------------------- /src/simulation/符合条件的子串.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 给定字符串str,给定一个整数n,得到字符串中连续出现次数为给定整数的所有子串,括号前两个数字是对应的下标位置 7 | 例如: 8 | 输入:abbcccddeefffgggcc 2 9 | 输出 (2,3,bb),(7,8,dd),(9,10,ee),(17,18,cc) 10 | */ 11 | public class 符合条件的子串 { 12 | public static StringBuilder sb = new StringBuilder(); 13 | 14 | public static String getConform(String str, int n) { 15 | int i = 1; 16 | int len = 1; 17 | for (; i < str.length(); i++) { 18 | if (str.charAt(i) == str.charAt(i - 1)) { 19 | len++; 20 | } else { 21 | if (len == n) {//发现不同,若此时刚好是n个 22 | sb.append("(").append(i - n).append(",").append(i - 1).append(","); 23 | for (int j = 0; j < n; j++) { 24 | sb.append(str.charAt(i - 1)); 25 | } 26 | sb.append("),"); 27 | } 28 | len = 1; 29 | } 30 | } 31 | if (len == n) { 32 | sb.append("(").append(i - n).append(",").append(i - 1).append(","); 33 | for (int j = 0; j < n; j++) { 34 | sb.append(str.charAt(i - 1)); 35 | } 36 | sb.append(")"); 37 | } 38 | return sb.toString(); 39 | } 40 | 41 | 42 | public static void main(String[] args) { 43 | Scanner sc = new Scanner(System.in); 44 | String str = sc.next(); 45 | int n = sc.nextInt(); 46 | 47 | String res = getConform(str, n); 48 | System.out.println(res); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/simulation/翻转数列.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.Scanner; 4 | 5 | /* 6 | 小Q定义了一种数列称为翻转数列: 7 | 给定整数n和m,满足n能被2m整除。对于一串连续递增整数数列1,2,3,4...每隔m个符号翻转一次,最初符号为'-'。 8 | 例如n = 8,m = 2,数列就是:-1,-2,+3,+4,-5,-6,+7,+8 9 | 而n = 4,m = 1,数列就是-1,+2,-3,+4 10 | 小Q现在希望你能帮他算算前n项和为多少。 11 | 12 | 输入描述: 13 | 输入包括两个整数n和m(2<=n<=10^9,1<=m),并且满足n能被2m整除。 14 | 输出描述: 15 | 输出一个整数,表示前n项和 16 | 8 2 17 | 8 18 | */ 19 | public class 翻转数列 { 20 | public static void main(String[] args) { 21 | Scanner sc = new Scanner(System.in); 22 | int n = sc.nextInt(); 23 | int m = sc.nextInt(); 24 | long sum = n / 2 * m; 25 | System.out.println(sum); 26 | } 27 | } 28 | /* 29 | 注:找规律,n能被2m整除是关键,隔m个为一组 30 | */ -------------------------------------------------------------------------------- /src/simulation/镜像回文.java: -------------------------------------------------------------------------------- 1 | package simulation; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @Desc 7 | * @Author ninja 8 | * @Date Created on 2020/4/8 9 | */ 10 | public class 镜像回文 { 11 | private final static Map map = new HashMap() {{ 12 | put('1', '1'); 13 | put('2', '5'); 14 | put('3', '8'); 15 | put('4', '7'); 16 | put('6', '9'); 17 | put('5', '2'); 18 | put('8', '3'); 19 | put('7', '4'); 20 | put('9', '6'); 21 | }}; 22 | 23 | public static void main(String[] args) { 24 | Scanner sc = new Scanner(System.in); 25 | int num = sc.nextInt(); 26 | List list = new ArrayList<>(); 27 | for (int i = 0; i < num; i++) { 28 | String s = sc.next(); 29 | list.add(s); 30 | } 31 | mirror(list); 32 | } 33 | 34 | private static void mirror(List list) { 35 | for (String s : list) { 36 | if (judge(s)) { 37 | System.out.println("YES"); 38 | } else { 39 | System.out.println("NO"); 40 | } 41 | } 42 | } 43 | 44 | private static boolean judge(String s) { 45 | String s1 = new StringBuilder(s).reverse().toString(); 46 | for (int i = 0; i < s1.length(); i++) { 47 | if (map.get(s.charAt(i)) != s1.charAt(i)) { 48 | return false; 49 | } 50 | } 51 | return true; 52 | } 53 | } 54 | --------------------------------------------------------------------------------