├── .gitignore ├── README.md └── codes ├── java ├── 4 │ └── src │ │ └── Solution.java ├── 5 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 6 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 7 │ └── src │ │ └── Solution.java ├── 8 │ └── src │ │ └── Solution.java ├── 9 │ └── src │ │ └── Solution.java ├── 10 │ └── src │ │ └── Solution.java ├── 11 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 12 │ └── src │ │ └── Solution.java ├── 15 │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ └── Solution2.java ├── 16 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 17 │ └── src │ │ └── Solution.java ├── 18 │ └── src │ │ └── Solution.java ├── 21 │ └── src │ │ └── Solution.java ├── 22 │ └── src │ │ └── Solution.java ├── 23 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 24 │ └── src │ │ └── Solution.java ├── 25 │ └── src │ │ └── Solution.java ├── 27 │ └── src │ │ └── Solution.java ├── 28 │ └── src │ │ └── Main.java ├── 29 │ └── src │ │ └── Solution.java ├── 30 │ └── src │ │ └── Solution.java ├── 31 │ └── src │ │ └── Solution.java ├── 32 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 33 │ └── src │ │ └── Solution.java ├── 34 │ └── src │ │ └── Solution.java ├── 35 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 36 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 37 │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ └── Solution2.java ├── 38 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 39 │ └── src │ │ └── Solution.java ├── 40 │ └── src │ │ └── Solution.java ├── 41 │ └── src │ │ └── Solution.java ├── 42 │ └── src │ │ └── Solution.java ├── 45 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 47 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 49 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 51 │ └── src │ │ ├── BFSolution.java │ │ ├── Solution2.java │ │ └── TestCase.java ├── 52 │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ └── Solution2.java ├── 54 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 55 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 56 │ └── src │ │ └── Solution.java ├── 58 │ └── src │ │ └── Solution.java ├── 61 │ └── src │ │ └── Solution.java ├── 62 │ └── src │ │ └── Solution.java ├── 64 │ └── src │ │ └── Solution.java ├── 65 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 67 │ └── src │ │ └── Solution.java ├── 10_3 │ └── src │ │ └── Solution.java ├── 32_3 │ └── src │ │ └── Solution.java ├── 51_1 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── TestCase.java ├── 55_2_IsBalanced │ └── src │ │ └── Solution.java ├── 58_2 │ └── src │ │ └── Solution.java ├── JumpFloor │ └── src │ │ └── Solution.java └── JumpFloorII │ └── src │ └── Solution.java └── python ├── 0 到 n-1 中缺失的数字.py ├── 10-1、跳台阶.py ├── 10-2、变态跳台阶.py ├── 12-矩阵中的路径.py ├── 13-机器人的运动范围.py ├── 14-剪绳子.py ├── 15、二进制中 1 的个数-1.py ├── 15、二进制中 1 的个数.py ├── 16-README.md ├── 16-数值的整数次方-1.py ├── 16-数值的整数次方.py ├── 18-删除链表中重复的结点.py ├── 19、正则表达式匹配.py ├── 19、正则表达式匹配(小 Fu 的做法).py ├── 20-表示数值的字符串.py ├── 21-调整数组顺序使奇数位于偶数前面.py ├── 22-链表中倒数第k个节点.py ├── 22-链表中倒数第k个节点(快慢指针).py ├── 22-链表中倒数第k个节点(练习).py ├── 23-链表中环的入口结点.py ├── 23-链表中环的入口结点(练习).py ├── 24-反转单链表.py ├── 24-反转单链表(Python 语法糖).py ├── 24-反转单链表(递归写法).py ├── 25、合并排序的链表-穿针引线.py ├── 25、合并排序的链表.py ├── 26.py ├── 27.py ├── 27、反转二叉树-后序遍历.py ├── 27、反转二叉树-层序遍历.py ├── 27、反转二叉树.py ├── 28-对称的二叉树.py ├── 28-对称的二叉树(使用双端队列的写法).py ├── 29.py ├── 3-不修改数组找出重复的数字.py ├── 3-数组中重复的数字.py ├── 3-数组中重复的数字(用位运算).py ├── 3-桶排序.py ├── 30-包含 min 的栈.py ├── 30-包含 min 的栈(大雪菜的做法).py ├── 31-栈的压入、弹出序列.py ├── 31.py ├── 32-不分行从上往下打印二叉树.py ├── 32-之字形打印二叉树.py ├── 32-分行从上往下打印二叉树.py ├── 33-二叉搜索树的后序遍历序列.py ├── 34-二叉树中和为某一值的路径.py ├── 34-二叉树中和为某一值的路径(解法2).py ├── 35-复杂链表的复刻.py ├── 35-复杂链表的复刻(书上介绍的方法).py ├── 36-二叉搜索树与双向链表.py ├── 36-二叉搜索树与双向链表(返回 tuple 的写法).py ├── 37-序列化、反序列化二叉树.py ├── 37-序列化、反序列化二叉树(解法2).py ├── 38-字符串的排列(重要,回溯,如何去掉重复元素)-大雪菜的做法.py ├── 38-字符串的排列(重要,回溯,如何去掉重复元素)-大雪菜的做法2.py ├── 38-字符串的排列(重要,回溯,如何去掉重复元素).py ├── 39-数组中出现次数超过一半的数字.py ├── 39-数组中出现次数超过一半的数字(牛客网).py ├── 4-二维数组中的查找.py ├── 4-二维数组中的查找(非二分).py ├── 40-最小的 K 个数(partition).py ├── 40-最小的 K 个数(二路-partition).py ├── 40-最小的 K 个数(小顶堆).py ├── 41-数据流中的中位数.py ├── 41-数据流中的中位数(更清晰的写法).py ├── 42-连续子数组的最大和.py ├── 43-整数中 1 出现的次数(从 1 到 n 整数中 1 出现的次数).py ├── 44-数字序列中某一位的数字.py ├── 45-把数组排成最小的数.py ├── 45-把数组排成最小的数(覆盖魔法函数).py ├── 46-把数字翻译成字符串.py ├── 47-礼物的最大价值.py ├── 49-丑数.py ├── 50-字符串中第一个只出现一次的字符.py ├── 50_2-字符流中第一个不重复的字符.py ├── 51-数组中的逆序对(分治解法).py ├── 51-数组中的逆序对(树状数组解法).py ├── 52-两个链表的第一个公共结点.py ├── 52-两个链表的第一个公共结点(用两个栈).py ├── 53-两个链表的第一个公共结点(最佳).py ├── 54-二叉搜索树的第 k 大结点.py ├── 55-二叉树的深度.py ├── 55_2-平衡二叉树-1.py ├── 55_2-平衡二叉树.py ├── 56-1-数组中只出现一次的两个数.py ├── 56-数字在排序数组中出现的次数.py ├── 56-数字在排序数组中出现的次数(解法2).py ├── 56-数字在排序数组中出现的次数(解法3-书上的写法).py ├── 56_2-数组中唯一只出现一次的数字.py ├── 57-和为 S 的连续正数序列.py ├── 58_1-翻转单词顺序列.py ├── 58_2-左旋转字符串.py ├── 59-滑动窗口的最大值.py ├── 6-从尾到头打印链表.py ├── 6-从尾到头打印链表(使用递归)-错误写法.py ├── 6-从尾到头打印链表(使用递归).py ├── 6-从尾到头打印链表(真正用栈).py ├── 60-n 个骰子的点数.py ├── 61-扑克牌的顺子.py ├── 62-圆圈中最后剩下的数字.py ├── 62-圆圈中最后剩下的数字(练习).py ├── 63-股票的最大利润.py ├── 63-股票的最大利润(贪心算法).py ├── 64-求 1 + 2 + 3 + ... + n.py ├── 65-不用加减乘除做加法-负数处理.py ├── 65-不用加减乘除做加法-负数处理1.py ├── 65-不用加减乘除做加法.py ├── 65-不用加减乘除做加法(位运算加法器).py ├── 65-不用加减乘除做加法(全加器2).py ├── 66-构建乘积数组.py ├── 67-把字符串转换成整数.py ├── 68-二叉树最近公共祖先.py ├── 7-重建二叉树.py ├── 8-二叉树的下一个结点.py ├── 9-1-用两个栈实现队列.py ├── 9-2-用队列实现栈.py ├── 数组中数值和下标相等的元素.py └── 题号未知-删除链表中的结点.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | */.idea/ 3 | */*.iml 4 | */out/ 5 | *.class 6 | *.iml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 《剑指 Offer》(第 2 版) 习题代码 2 | 3 | Python 全部都写了,Java 不全。 4 | 5 | 题解写在了下面的文章中。 6 | 7 | | 文章 | 文章链接 | 8 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 9 | | 《剑指 Offer》(第 2 版) 题解(Python 语言实现)第 01-10 题 | [文章链接](https://liweiwei1419.github.io/blog/2018/12/10/sword-for-offer-solutions/1-10/) | 10 | | 《剑指 Offer》(第 2 版) 题解(Python 语言实现)第 11-20 题 | [文章链接](https://liweiwei1419.github.io/blog/2018/12/11/sword-for-offer-solutions/11-20/) | 11 | | 《剑指 Offer》(第 2 版) 题解(Python 语言实现)第 21-30 题 | [文章链接](https://liweiwei1419.github.io/blog/2018/12/12/sword-for-offer-solutions/21-30/) | 12 | | 《剑指 Offer》(第 2 版) 题解(Python 语言实现)第 31-40 题 | [文章链接](https://liweiwei1419.github.io/blog/2018/12/13/sword-for-offer-solutions/31-40/) | 13 | | 《剑指 Offer》(第 2 版) 题解(Python 语言实现)第 41-50 题 | [文章链接](https://liweiwei1419.github.io/blog/2018/12/14/sword-for-offer-solutions/41-50/) | 14 | | 《剑指 Offer》(第 2 版) 题解(Python 语言实现)第 51-60 题 | [文章链接](https://liweiwei1419.github.io/blog/2018/12/15/sword-for-offer-solutions/51-60/) | 15 | | 《剑指 Offer》(第 2 版) 题解(Python 语言实现)第 61-68 题 | [文章链接](https://liweiwei1419.github.io/blog/2018/12/16/sword-for-offer-solutions/61-68/) | 16 | 17 | 简书:[《剑指 Offer》(第 2 版)读书笔记](https://www.jianshu.com/nb/33634205)。 18 | 19 | mkdocs 静态文档:[https://liweiwei1419.github.io/sword-for-offer/](https://liweiwei1419.github.io/sword-for-offer/)。 -------------------------------------------------------------------------------- /codes/java/10/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 1 1 2 3 5 8 4 | // 0 1 2 3 4 5 5 | public int Fibonacci(int n) { 6 | if (n == 0) { 7 | return 0; 8 | } 9 | if (n == 1) { 10 | return 1; 11 | } 12 | int[] dp = new int[n + 1]; 13 | dp[0] = 0; 14 | dp[1] = 1; 15 | for (int i = 2; i <= n; i++) { 16 | dp[i] = dp[i - 1] + dp[i - 2]; 17 | } 18 | return dp[n]; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Solution solution = new Solution(); 23 | int fibonacci = solution.Fibonacci(5); 24 | System.out.println(fibonacci); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /codes/java/10_3/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | // 本质还是斐波拉契数列问题,要注意: 3 | // (1)首先判断极端情况 4 | // (2)如何减少空间复杂度 5 | public int RectCover(int target) { 6 | int n = target; 7 | if (n == 0) { 8 | return 0; 9 | } 10 | int[] dp = new int[n + 1]; 11 | dp[0] = 1; 12 | dp[1] = 1; 13 | for (int i = 2; i <= n; i++) { 14 | dp[i] = dp[i - 1] + dp[i - 2]; 15 | } 16 | return dp[n]; 17 | } 18 | 19 | // 最佳解法 20 | public int RectCover1(int target) { 21 | if (target <= 2) { 22 | return target; 23 | } 24 | int a = 1; 25 | int b = 2; 26 | int c = 0; 27 | for (int i = 3; i <= target; i++) { 28 | c = a + b; 29 | a = b; 30 | b = c; 31 | } 32 | return c; 33 | } 34 | 35 | // 参考资料:http://cuijiahua.com/blog/2017/11/basis_10.html 36 | public static void main(String[] args) { 37 | Solution solution = new Solution(); 38 | int n = 10; 39 | for (int i = 0; i < n; i++) { 40 | int rectCover = solution.RectCover(i); 41 | int rectCover1 = solution.RectCover1(i); 42 | System.out.println(rectCover + "\t" + rectCover1); 43 | if (rectCover != rectCover1) { 44 | System.out.println("解法错误!"); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /codes/java/11/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 虽然可以通过,但是 O(n) 的复杂度并不理想 4 | public int minNumberInRotateArray(int[] array) { 5 | // {3,4,5,1,2} 6 | // 1 2 3 4 5 7 | int len = array.length; 8 | for (int i = 1; i < len - 1; i++) { 9 | if (array[i] < array[i - 1]) { 10 | return array[i]; 11 | } 12 | } 13 | // 如果走到这里,说明数组是升序的,直接返回第 0 号索引的元素就可以了 14 | return array[0]; 15 | } 16 | 17 | public static void main(String[] args) { 18 | // int[] nums = new int[]{3, 4, 5, 1, 2}; 19 | int[] nums = new int[]{1, 2, 3, 4, 5}; 20 | Solution solution = new Solution(); 21 | int minNumberInRotateArray = solution.minNumberInRotateArray(nums); 22 | System.out.println(minNumberInRotateArray); 23 | } 24 | } -------------------------------------------------------------------------------- /codes/java/11/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * https://www.nowcoder.com/questionTerminal/9f3231a991af4f55b95579b44b7a01ba 3 | * 4 | * @author liwei 5 | */ 6 | public class Solution2 { 7 | 8 | public int minNumberInRotateArray(int[] array) { 9 | int len = array.length; 10 | if (len == 0) { 11 | return 0; 12 | } 13 | int first = 0; 14 | int last = len - 1; 15 | while (first < last) { 16 | int mid = first + (last - first) / 2; 17 | if (array[mid] > array[last]) { 18 | first = mid + 1; 19 | } else if (array[mid] == array[last]) { 20 | last = last - 1; 21 | } else { 22 | last = mid; 23 | } 24 | } 25 | return array[first]; 26 | } 27 | 28 | public static void main(String[] args) { 29 | // int[] nums = new int[]{3}; 30 | // int[] nums = new int[]{3, 4, 5, 6, 7, 8, 9, 1, 2}; 31 | // int[] nums = new int[]{1, 2, 3, 4, 5}; 32 | int[] nums = new int[]{2, 2, 2, 1, 2}; 33 | Solution2 solution2 = new Solution2(); 34 | int minNumberInRotateArray = solution2.minNumberInRotateArray(nums); 35 | System.out.println(minNumberInRotateArray); 36 | } 37 | } -------------------------------------------------------------------------------- /codes/java/15/src/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/20 下午5:34 4 | */ 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | 9 | String nine = Integer.toBinaryString(-9); 10 | // 输出 11111111111111111111111111110111 11 | System.out.println(nine); 12 | 13 | System.out.println(Integer.toBinaryString(Integer.MAX_VALUE)); 14 | 15 | System.out.println("11111111111111111111111111110111".length()); 16 | 17 | System.out.println((double) 1/8); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /codes/java/15/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | public int NumberOf1(int n) { 3 | int count = 0; 4 | // 负数左移的时候,最高位补 1,因此,为了避免死循环,先要把最高位变成 0 5 | // 负数左移的时候,最高位补 1,因此,为了避免死循环,先要把最高位变成 0 6 | // 负数左移的时候,最高位补 1,因此,为了避免死循环,先要把最高位变成 0 7 | 8 | // 为负数的时候,将最高位的 1 变成 0 9 | // 即由负数变成正数,然后再计算 1 的个数 10 | if (n < 0) { 11 | n = n & Integer.MAX_VALUE; 12 | count++; 13 | } 14 | 15 | // 当 n 是正数的时候,计算 1 的个数 16 | while (n != 0) { 17 | count += n & 1; 18 | n = n >> 1; 19 | } 20 | return count; 21 | } 22 | } -------------------------------------------------------------------------------- /codes/java/15/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/16 上午11:07 4 | */ 5 | public class Solution2 { 6 | /*** 7 | * 可以使用 1001 作为测试用例来理解,a&(a-1) 的结果会将 a 最右边的 1 变为 0 ,直到 a = 0, 8 | * 还可以先将 a&1 != 0,然后右移 1 位,但不能计算负数的值 9 | * @param n 10 | * @return 11 | */ 12 | public int NumberOf1(int n) { 13 | int count = 0; 14 | while (n != 0) { 15 | count++; 16 | n = (n - 1) & n; 17 | } 18 | return count; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /codes/java/16/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public double Power(double base, int exponent) { 4 | if (exponent == 0) { 5 | return 1; 6 | } 7 | if (exponent < 0) { 8 | return 1 / Power(base, -exponent); 9 | } 10 | // 使用位运算的 与 运算符代替了求余数运算,来判断一个数是奇数还是偶数 11 | if ((exponent & 1) == 0) { 12 | // 等价于 exponent 是偶数 13 | double square = Power(base, exponent >> 1); 14 | return square * square; 15 | } else { 16 | // 是奇数的时候 17 | double square = Power(base, (exponent - 1) >> 1); 18 | return square * square * base; 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | int base = 3; 24 | int exponent = -3; 25 | Solution solution = new Solution(); 26 | double result1 = solution.Power(base, exponent); 27 | System.out.println(result1); 28 | exponent = 6; 29 | double result2 = solution.Power(base, exponent); 30 | System.out.println(result2); 31 | // exponent 指数,exponent >> 1 表示将指数除以 2 32 | System.out.println(exponent >> 1); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /codes/java/16/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/19 上午9:22 4 | */ 5 | public class Solution2 { 6 | 7 | public double Power(double base, int exponent) { 8 | // 不能用 == 比较两个浮点数是否相等,因为有误差。 9 | if (equals(base, 0) && exponent < 0) { 10 | throw new IllegalArgumentException("当底数为 0 的时候,指数为负数没有意义"); 11 | } 12 | if (exponent == 0) { 13 | return 1.0; 14 | } 15 | if (exponent > 0) { 16 | return power(base, exponent); 17 | } else { 18 | return power(1 / base, -exponent); 19 | } 20 | } 21 | 22 | public double power(double base, int exponent) { 23 | if (exponent == 0) { 24 | return 1.0; 25 | } 26 | if (exponent % 2 == 0) { 27 | double square = power(base, exponent / 2); 28 | return square * square; 29 | } else { 30 | double square = power(base, (exponent - 1) / 2); 31 | return square * square * base; 32 | } 33 | } 34 | 35 | private boolean equals(double num1, double num2) { 36 | return num1 - num2 < 0.000001 && num1 - num2 > -0.000001; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /codes/java/17/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | import java.util.Stack; 4 | 5 | public class Solution { 6 | 7 | private List res; 8 | 9 | private void findPermutation(int hasUsedCount, int n, Stack pre) { 10 | if (hasUsedCount == n) { 11 | // 打印 pre 12 | String integerStr = listToString(pre); 13 | if (!"".equals(integerStr)) { 14 | res.add(integerStr); 15 | } 16 | return; 17 | } 18 | for (int i = 0; i < 10; i++) { 19 | pre.add(i); 20 | findPermutation(hasUsedCount + 1, n, pre); 21 | // 这一步很关键,下一轮循环,我得换一个数 22 | pre.pop(); 23 | } 24 | } 25 | 26 | private String listToString(Stack pre) { 27 | StringBuilder stringBuilder = new StringBuilder(); 28 | // 遇到不为零的数字,就打开字符串拼接的功能 29 | boolean startPrint = false; 30 | for (int i = 0; i < pre.size(); i++) { 31 | // !startPrint 前面加上这个判断,打开输出以后,就不用每次都判断拿出来的数等不等于 0 了 32 | if (!startPrint && pre.get(i) != 0) { 33 | startPrint = true; 34 | } 35 | if (startPrint) { 36 | stringBuilder.append(pre.get(i)); 37 | } 38 | } 39 | return stringBuilder.toString(); 40 | } 41 | 42 | /** 43 | * 入口函数 44 | * @param n 45 | * @return 46 | */ 47 | public List print1ToMaxOfNDigits(int n) { 48 | res = new ArrayList<>(); 49 | if (n <= 0) { 50 | return res; 51 | } 52 | // 转换成排列问题 53 | Stack pre = new Stack<>(); 54 | findPermutation(0, n, pre); 55 | return res; 56 | } 57 | 58 | public static void main(String[] args) { 59 | int n = 3; 60 | Solution solution = new Solution(); 61 | List print1ToMaxOfNDigits = solution.print1ToMaxOfNDigits(n); 62 | System.out.println(print1ToMaxOfNDigits); 63 | System.out.println(n + " 位数有多少个:" + print1ToMaxOfNDigits.size()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /codes/java/18/src/Solution.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next = null; 4 | 5 | ListNode(int val) { 6 | this.val = val; 7 | } 8 | 9 | public ListNode(int[] arr) { 10 | if (arr == null || arr.length == 0) { 11 | throw new IllegalArgumentException("arr can not be empty"); 12 | } 13 | this.val = arr[0]; 14 | ListNode cur = this; 15 | for (int i = 1; i < arr.length; i++) { 16 | cur.next = new ListNode(arr[i]); 17 | cur = cur.next; 18 | } 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | StringBuilder s = new StringBuilder(); 24 | ListNode cur = this; 25 | while (cur != null) { 26 | s.append(cur.val + " -> "); 27 | cur = cur.next; 28 | } 29 | s.append("NULL"); 30 | return s.toString(); 31 | } 32 | } 33 | 34 | public class Solution { 35 | public ListNode deleteDuplication(ListNode pHead) { 36 | ListNode dummyNode = new ListNode(-1); 37 | dummyNode.next = pHead; 38 | ListNode curNode = dummyNode; 39 | while (curNode.next != null && curNode.next.next != null) { 40 | ListNode next = curNode.next; 41 | ListNode nextNext = next.next; 42 | if (next.val == nextNext.val) { 43 | while (nextNext.next != null && nextNext.val == nextNext.next.val) { 44 | nextNext = nextNext.next; 45 | } 46 | ListNode delNode = nextNext; 47 | curNode.next = delNode.next; 48 | delNode.next = null; 49 | } else { 50 | curNode = curNode.next; 51 | } 52 | } 53 | return dummyNode.next; 54 | } 55 | 56 | 57 | public static void main(String[] args) { 58 | int[] nums = new int[]{1, 2, 3, 3, 4, 4, 5}; 59 | ListNode head = new ListNode(nums); 60 | System.out.println(head); 61 | 62 | Solution solution = new Solution(); 63 | ListNode deleteDuplication = solution.deleteDuplication(head); 64 | System.out.println(deleteDuplication); 65 | } 66 | } -------------------------------------------------------------------------------- /codes/java/21/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | // 保证奇数和奇数,偶数和偶数之间的相对位置不变。 5 | public void reOrderArray(int[] array) { 6 | int len = array.length; 7 | if (len == 0) { 8 | return; 9 | } 10 | // 奇数全部挪到缓存数组中 11 | int[] buff = new int[len]; 12 | int j = -1; 13 | for (int i = 0; i < len; i++) { 14 | if (array[i] % 2 == 1) { 15 | j++; 16 | buff[j] = array[i]; 17 | } 18 | } 19 | // 如果没有奇数,直接返回就可以了 20 | if (j == -1) { 21 | return; 22 | } 23 | // 从后向前赋值 24 | int k = len - 1; 25 | for (int i = len - 1; i >= 0; i--) { 26 | if (array[i] % 2 == 0) { 27 | array[k] = array[i]; 28 | k--; 29 | } 30 | } 31 | while (j >= 0) { 32 | array[j] = buff[j]; 33 | j--; 34 | } 35 | } 36 | 37 | public static void main(String[] args) { 38 | int[] arr = {1, 2, 3, 4, 5}; 39 | Solution solution = new Solution(); 40 | solution.reOrderArray(arr); 41 | System.out.println(Arrays.toString(arr)); 42 | } 43 | } -------------------------------------------------------------------------------- /codes/java/22/src/Solution.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next = null; 4 | 5 | ListNode(int val) { 6 | this.val = val; 7 | } 8 | } 9 | 10 | public class Solution { 11 | 12 | public ListNode FindKthToTail(ListNode head, int k) { 13 | // 注意点1:极端输入直接输出结果 14 | if (head == null) { 15 | return null; 16 | } 17 | ListNode dummyNode = new ListNode(-1); 18 | dummyNode.next = head; 19 | ListNode fast = dummyNode; 20 | for (int i = 0; i < k; i++) { 21 | fast = fast.next; 22 | // 注意点2:对不符合要求的输入的判断 23 | if (fast == null) { 24 | return null; 25 | } 26 | } 27 | ListNode slow = dummyNode; 28 | while (fast != null) { 29 | fast = fast.next; 30 | slow = slow.next; 31 | } 32 | return slow; 33 | } 34 | } -------------------------------------------------------------------------------- /codes/java/23/src/Solution.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next = null; 4 | 5 | ListNode(int val) { 6 | this.val = val; 7 | } 8 | } 9 | 10 | public class Solution { 11 | 12 | public ListNode EntryNodeOfLoop(ListNode pHead) { 13 | // ListNode node1 = new ListNode(1); 14 | // ListNode node2 = new ListNode(2); 15 | // node1.next = node2; 16 | // node2.next = node1; 17 | 18 | // node node 19 | if (pHead == null || pHead.next == null || pHead.next.next == null) { 20 | return null; 21 | } 22 | ListNode fast = pHead.next.next; 23 | ListNode slow = pHead.next; 24 | // 先判断有没有环 25 | while (fast != slow) { 26 | if (fast.next != null && fast.next.next != null) { 27 | fast = fast.next.next; 28 | slow = slow.next; 29 | } else { 30 | // 没有环,返回 31 | return null; 32 | } 33 | } 34 | // 跳出循环的时候,链表中的部分构成环 35 | fast = pHead; 36 | while (fast != slow) { 37 | fast = fast.next; 38 | slow = slow.next; 39 | } 40 | return slow; 41 | } 42 | } -------------------------------------------------------------------------------- /codes/java/23/src/Solution2.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next = null; 4 | 5 | ListNode(int val) { 6 | this.val = val; 7 | } 8 | } 9 | 10 | 11 | public class Solution { 12 | 13 | public ListNode EntryNodeOfLoop(ListNode pHead) { 14 | 15 | // 先考虑好极端情况 16 | // 空结点、只有一个结点、两个结点(不互相指向) 17 | if (pHead == null || pHead.next == null || pHead.next.next == null) { 18 | return null; 19 | } 20 | 21 | // 注意:一开始呀先让 slow 和 fast 走一定步数, 22 | // 否则起点一样,fast != slow 就永远不成立了!!! 23 | // 解决这道问题要用一些数论的知识 24 | ListNode slow = pHead.next; 25 | ListNode fast = pHead.next.next; 26 | // ListNode slow = pHead; 27 | // ListNode fast = pHead; 28 | while (fast.next != null && fast.next.next != null && fast != slow) { 29 | slow = slow.next; 30 | fast = fast.next.next; 31 | } 32 | if (fast.next == null || fast.next.next == null) { 33 | return null; 34 | } 35 | // 走到这里一定满足 fast == slow 36 | assert fast == slow; 37 | // 复位到开头 38 | fast = pHead; 39 | while (fast != slow) { 40 | fast = fast.next; 41 | slow = slow.next; 42 | } 43 | return fast; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /codes/java/24/src/Solution.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next = null; 4 | 5 | ListNode(int val) { 6 | this.val = val; 7 | } 8 | } 9 | 10 | public class Solution { 11 | 12 | // 递归写法要画个图就清楚了 13 | public ListNode ReverseList(ListNode head) { 14 | if (head == null || head.next == null) { 15 | return head; 16 | } 17 | ListNode next = head.next; 18 | ListNode newHead = ReverseList(next); 19 | next.next = head; 20 | head.next = null; 21 | return newHead; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /codes/java/25/src/Solution.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next = null; 4 | 5 | ListNode(int val) { 6 | this.val = val; 7 | } 8 | } 9 | 10 | public class Solution { 11 | public ListNode Merge(ListNode list1, ListNode list2) { 12 | if (list1 == null) { 13 | return list2; 14 | } 15 | if (list2 == null) { 16 | return list1; 17 | } 18 | if (list1.val < list2.val) { 19 | list1.next = Merge(list1.next, list2); 20 | return list1; 21 | } else { 22 | list2.next = Merge(list1, list2.next); 23 | return list2; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /codes/java/27/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val = 0; 3 | TreeNode left = null; 4 | TreeNode right = null; 5 | 6 | public TreeNode(int val) { 7 | this.val = val; 8 | 9 | } 10 | } 11 | 12 | public class Solution { 13 | 14 | // 前序遍历和后序遍历都是可以的 15 | public void Mirror(TreeNode root) { 16 | if (root == null) { 17 | return; 18 | } 19 | TreeNode temp = root.left; 20 | root.left = root.right; 21 | root.right = temp; 22 | Mirror(root.left); 23 | Mirror(root.right); 24 | } 25 | 26 | public void Mirror1(TreeNode root) { 27 | if (root == null) { 28 | return; 29 | } 30 | Mirror(root.left); 31 | Mirror(root.right); 32 | TreeNode temp = root.left; 33 | root.left = root.right; 34 | root.right = temp; 35 | } 36 | } -------------------------------------------------------------------------------- /codes/java/28/src/Main.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val = 0; 3 | TreeNode left = null; 4 | TreeNode right = null; 5 | 6 | public TreeNode(int val) { 7 | this.val = val; 8 | 9 | } 10 | } 11 | 12 | public class Solution { 13 | boolean isSymmetrical(TreeNode pRoot) { 14 | if (pRoot == null) { 15 | return true; 16 | } 17 | return helper(pRoot.left, pRoot.right); 18 | } 19 | 20 | private boolean helper(TreeNode pRoot1, TreeNode pRoot2) { 21 | if (pRoot1 == null && pRoot2 == null) { 22 | return true; 23 | } 24 | if (pRoot1 == null || pRoot2 == null || pRoot1.val != pRoot2.val) { 25 | return false; 26 | } 27 | return helper(pRoot1.left, pRoot2.right) && helper(pRoot1.right, pRoot2.left); 28 | } 29 | } -------------------------------------------------------------------------------- /codes/java/30/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Stack; 2 | 3 | public class Solution { 4 | 5 | private Stack minStack = new Stack<>(); 6 | private Stack dataStack = new Stack<>(); 7 | 8 | public void push(int node) { 9 | if (minStack.isEmpty()) { 10 | minStack.push(node); 11 | dataStack.push(node); 12 | return; 13 | } 14 | int curMin = minStack.peek(); 15 | if (node < curMin) { 16 | minStack.push(node); 17 | } else { 18 | minStack.push(curMin); 19 | } 20 | dataStack.push(node); 21 | } 22 | 23 | public void pop() { 24 | minStack.pop(); 25 | dataStack.pop(); 26 | } 27 | 28 | public int top() { 29 | return dataStack.pop(); 30 | } 31 | 32 | public int min() { 33 | return minStack.peek(); 34 | } 35 | } -------------------------------------------------------------------------------- /codes/java/31/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.Stack; 3 | 4 | public class Solution { 5 | 6 | // 这道题花了好长时间,不过终于思路清晰了 7 | public boolean IsPopOrder(int[] pushA, int[] popA) { 8 | int lenA = pushA.length; 9 | int lenB = popA.length; 10 | if (lenA != lenB) { 11 | return false; 12 | } 13 | 14 | // 把两个数组放入一个队列中,是为了方便遍历 15 | LinkedList queue1 = new LinkedList<>(); 16 | for (int i = 0; i < lenA; i++) { 17 | queue1.addLast(pushA[i]); 18 | } 19 | LinkedList queue2 = new LinkedList<>(); 20 | for (int i = 0; i < lenA; i++) { 21 | queue2.addLast(popA[i]); 22 | } 23 | 24 | Stack stack = new Stack<>(); 25 | // 以上的代码虽然长,但也只是做了一些极端测试用例的考虑和变量的初始化工作 26 | 27 | // 步骤1: 28 | // 把原始数组形成的队列遍历完成, 29 | // 只要是与栈数组形成的队列的队首元素不等的,都放入一个辅助栈中 30 | while (!queue1.isEmpty()) { 31 | int peekFirst1 = queue1.removeFirst(); 32 | int peekFirst2 = queue2.peekFirst(); 33 | 34 | if (peekFirst1 != peekFirst2) { 35 | stack.add(peekFirst1); 36 | } else { 37 | queue2.removeFirst(); 38 | } 39 | 40 | } 41 | // 步骤 2:陆续弹出栈,遍历栈数组形成的队列,只要不等就表示不符合题目要求 42 | while (!stack.isEmpty()) { 43 | if (!queue2.removeFirst().equals(stack.pop())) { 44 | return false; 45 | } 46 | } 47 | // 步骤 3:能走到最后的,说明符合题目要求 48 | return true; 49 | } 50 | 51 | public static void main(String[] args) { 52 | Solution solution = new Solution(); 53 | // int[] pushA = new int[]{1, 2, 3, 4, 5}; 54 | // int[] popA = new int[]{4, 5, 3, 2, 1}; 55 | int[] pushA = new int[]{1}; 56 | int[] popA = new int[]{1}; 57 | boolean isPopOrder = solution.IsPopOrder(pushA, popA); 58 | System.out.println(isPopOrder); 59 | } 60 | } -------------------------------------------------------------------------------- /codes/java/32/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.LinkedList; 3 | 4 | class TreeNode { 5 | int val = 0; 6 | TreeNode left = null; 7 | TreeNode right = null; 8 | 9 | public TreeNode(int val) { 10 | this.val = val; 11 | } 12 | } 13 | 14 | public class Solution { 15 | public ArrayList PrintFromTopToBottom(TreeNode root) { 16 | ArrayList res = new ArrayList<>(); 17 | if (root == null) { 18 | return res; 19 | } 20 | LinkedList queue = new LinkedList<>(); 21 | queue.addLast(root); 22 | while (!queue.isEmpty()) { 23 | int curSize = queue.size(); 24 | for (int i = 0; i < curSize; i++) { 25 | TreeNode curNode = queue.removeFirst(); 26 | res.add(curNode.val); 27 | if (curNode.left != null) { 28 | queue.addLast(curNode.left); 29 | } 30 | if (curNode.right != null) { 31 | queue.addLast(curNode.right); 32 | } 33 | } 34 | } 35 | return res; 36 | } 37 | 38 | public static void main(String[] args) { 39 | TreeNode node8 = new TreeNode(8); 40 | TreeNode node6 = new TreeNode(6); 41 | TreeNode node10 = new TreeNode(10); 42 | TreeNode node5 = new TreeNode(5); 43 | TreeNode node7 = new TreeNode(7); 44 | TreeNode node9 = new TreeNode(9); 45 | TreeNode node11 = new TreeNode(11); 46 | 47 | node8.left = node6; 48 | node8.right = node10; 49 | 50 | node6.left = node5; 51 | node6.right = node7; 52 | 53 | node10.left = node9; 54 | node10.right = node11; 55 | 56 | Solution solution = new Solution(); 57 | ArrayList printFromTopToBottom = solution.PrintFromTopToBottom(node8); 58 | System.out.println(printFromTopToBottom); 59 | } 60 | } -------------------------------------------------------------------------------- /codes/java/32/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.LinkedList; 3 | 4 | 5 | class TreeNode { 6 | int val = 0; 7 | TreeNode left = null; 8 | TreeNode right = null; 9 | 10 | public TreeNode(int val) { 11 | this.val = val; 12 | 13 | } 14 | 15 | } 16 | 17 | // 从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。 18 | // 层序遍历 19 | public class Solution { 20 | ArrayList> Print(TreeNode pRoot) { 21 | ArrayList> res = new ArrayList>(); 22 | if (pRoot == null) { 23 | return res; 24 | } 25 | LinkedList queue = new LinkedList<>(); 26 | queue.addLast(pRoot); 27 | 28 | while (!queue.isEmpty()) { 29 | int size = queue.size(); 30 | 31 | ArrayList curLevel = new ArrayList<>(); 32 | for (int i = 0; i < size; i++) { 33 | TreeNode top = queue.removeFirst(); 34 | curLevel.add(top.val); 35 | if (top.left != null) { 36 | queue.addLast(top.left); 37 | } 38 | if (top.right != null) { 39 | queue.addLast(top.right); 40 | } 41 | 42 | } 43 | res.add(curLevel); 44 | } 45 | return res; 46 | } 47 | } -------------------------------------------------------------------------------- /codes/java/32_3/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.LinkedList; 3 | import java.util.Stack; 4 | 5 | class TreeNode { 6 | int val = 0; 7 | TreeNode left = null; 8 | TreeNode right = null; 9 | 10 | public TreeNode(int val) { 11 | this.val = val; 12 | 13 | } 14 | 15 | } 16 | 17 | // 1 18 | // 3 2 19 | // 4 5 6 20 | //12 11 10 9 8 7 21 | // 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印, 22 | // 第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。 23 | public class Solution { 24 | public ArrayList> Print(TreeNode pRoot) { 25 | ArrayList> res = new ArrayList<>(); 26 | if (pRoot == null) { 27 | return res; 28 | } 29 | LinkedList queue = new LinkedList<>(); 30 | queue.addLast(pRoot); 31 | boolean right = true; 32 | while (!queue.isEmpty()) { 33 | int size = queue.size(); 34 | // 之 字形 一开始向右 35 | ArrayList curLevel = new ArrayList<>(); 36 | Stack stack = new Stack<>(); 37 | for (int i = 0; i < size; i++) { 38 | if (right) { 39 | TreeNode node = queue.removeFirst(); 40 | curLevel.add(node.val); 41 | if (node.left != null) { 42 | stack.add(node.left); 43 | } 44 | if (node.right != null) { 45 | stack.add(node.right); 46 | } 47 | } else { 48 | TreeNode node = queue.removeFirst(); 49 | curLevel.add(node.val); 50 | if (node.right != null) { 51 | stack.add(node.right); 52 | } 53 | if (node.left != null) { 54 | stack.add(node.left); 55 | } 56 | } 57 | } 58 | while (!stack.isEmpty()) { 59 | queue.addLast(stack.pop()); 60 | } 61 | right = !right; 62 | res.add(curLevel); 63 | } 64 | return res; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /codes/java/33/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | public boolean VerifySquenceOfBST(int[] sequence) { 3 | int len = sequence.length; 4 | if (len == 0) { 5 | return false; 6 | } 7 | if (len == 1) { 8 | return true; 9 | } 10 | int l = 0; 11 | int r = len - 1; 12 | while (l <= r) { 13 | int mid = judgeBST(sequence, l, r); 14 | if (mid == -1) { 15 | return false; 16 | } 17 | // 注意考虑数组下标越界的问题 18 | // return (mid > 1 ? judgeBST(sequence, l, mid - 1) != -1 : true) && judgeBST(sequence, mid, r) != -1; 19 | return (mid <= 1 || judgeBST(sequence, l, mid - 1) != -1) && judgeBST(sequence, mid, r) != -1; 20 | } 21 | return true; 22 | } 23 | 24 | // mid 以及 mid 以后的数子都小于 arr[r] 25 | private int judgeBST(int[] arr, int l, int r) { 26 | int p = arr[r]; 27 | int i = l; 28 | int mid; 29 | // 5,4,3,2,1 30 | while (arr[i] < p) { 31 | i++; 32 | } 33 | mid = i; 34 | while (arr[i] > p && i < r) { 35 | i++; 36 | } 37 | // 如果遍历到末尾了,就说明,在这一层,是可以构成 BST 的 38 | if (i == r) { 39 | return mid; 40 | } 41 | return -1; 42 | } 43 | 44 | public static void main(String[] args) { 45 | // int[] nums1 = {5, 7, 6, 9, 11, 10, 8}; 46 | int[] nums = {5, 4, 3, 2, 1}; 47 | Solution solution = new Solution(); 48 | boolean verifySquenceOfBST = solution.VerifySquenceOfBST(nums); 49 | System.out.println(verifySquenceOfBST); 50 | } 51 | } -------------------------------------------------------------------------------- /codes/java/34/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Stack; 3 | 4 | class TreeNode { 5 | int val = 0; 6 | TreeNode left = null; 7 | TreeNode right = null; 8 | 9 | public TreeNode(int val) { 10 | this.val = val; 11 | 12 | } 13 | } 14 | 15 | public class Solution { 16 | // 使用搜索的策略可以完成 17 | public ArrayList> FindPath(TreeNode root, int target) { 18 | ArrayList> res = new ArrayList<>(); 19 | Stack pre = new Stack<>(); 20 | findPath(root, target, pre, res); 21 | return res; 22 | } 23 | 24 | private void findPath(TreeNode root, int target, Stack pre, ArrayList> res) { 25 | if (root == null || root.val > target) { 26 | return; 27 | } 28 | // 注意:题目中问的是到叶子结点 29 | if (root.val == target && root.left == null && root.right == null) { 30 | pre.add(root.val); 31 | res.add(new ArrayList<>(pre)); 32 | pre.pop(); 33 | return; 34 | } 35 | assert root.val < target && root != null; 36 | pre.add(root.val); 37 | findPath(root.left, target - root.val, pre, res); 38 | findPath(root.right, target - root.val, pre, res); 39 | pre.pop(); 40 | } 41 | 42 | public static void main(String[] args) { 43 | TreeNode node1 = new TreeNode(1); 44 | TreeNode node2 = new TreeNode(2); 45 | TreeNode node3 = new TreeNode(3); 46 | TreeNode node4 = new TreeNode(4); 47 | TreeNode node8 = new TreeNode(8); 48 | TreeNode node7 = new TreeNode(7); 49 | 50 | node1.left = node2; 51 | node1.right = node3; 52 | 53 | node2.left = node4; 54 | node2.right = node8; 55 | 56 | node3.left = node7; 57 | 58 | Solution solution = new Solution(); 59 | ArrayList> findPath = solution.FindPath(node1, 11); 60 | System.out.println(findPath); 61 | } 62 | } -------------------------------------------------------------------------------- /codes/java/35/src/Solution.java: -------------------------------------------------------------------------------- 1 | class RandomListNode { 2 | int label; 3 | RandomListNode next = null; 4 | RandomListNode random = null; 5 | 6 | RandomListNode(int label) { 7 | this.label = label; 8 | } 9 | } 10 | 11 | public class Solution { 12 | public RandomListNode Clone(RandomListNode pHead) { 13 | // 极端情况,一定要写先出来 14 | if (pHead == null) { 15 | return null; 16 | } 17 | 18 | RandomListNode curNode = pHead; 19 | // 第 1 步:根据 next 指针复制出一个新旧合一的链表 20 | // 此时,奇数索引(从 1 开始计算)的结点是旧的结点,偶数索引的结点是新的结点 21 | RandomListNode nextNode; 22 | RandomListNode copyNode; 23 | while (curNode != null) { 24 | nextNode = curNode.next; 25 | copyNode = new RandomListNode(curNode.label); 26 | curNode.next = copyNode; 27 | copyNode.next = nextNode; 28 | curNode = nextNode; 29 | } 30 | 31 | // 第 2 步:根据旧结点 random 指针,给新结点的 random 指针做出正确的指向 32 | // 指针复位到起始结点 33 | curNode = pHead; 34 | while (curNode != null) { 35 | copyNode = curNode.next; 36 | nextNode = copyNode.next; 37 | // 特别注意 38 | // 特别注意 39 | // 特别注意:有的结点很可能 random 的指向为空(题目中明确说明) 40 | // 所以:只要遇到 next 引用的时候,一定要注意判断是否为空 41 | copyNode.random = curNode.random == null ? null : curNode.random.next; 42 | curNode = nextNode; 43 | } 44 | 45 | // 第 3 步:旧结点和新结点分离(拆分链表) 46 | curNode = pHead; 47 | RandomListNode res = pHead.next; 48 | while (curNode != null) { 49 | copyNode = curNode.next; 50 | nextNode = copyNode.next; 51 | // 恢复原始结点 52 | curNode.next = copyNode.next; 53 | // 恢复拷贝结点 54 | // 这里也要同样注意空指针的问题,克隆结点的最后一个结点的下一个结点是 null 55 | copyNode.next = copyNode.next == null ? null : copyNode.next.next; 56 | curNode = nextNode; 57 | } 58 | return res; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /codes/java/35/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 同 Solution,来自参考解答 3 | */ 4 | public class Solution2 { 5 | public RandomListNode Clone(RandomListNode pHead) { 6 | if (pHead == null) { 7 | return null; 8 | } 9 | RandomListNode currentNode = pHead; 10 | //1、复制每个结点,如复制结点 A 得到 A1,将结点 A1 插到结点 A 后面; 11 | while (currentNode != null) { 12 | RandomListNode cloneNode = new RandomListNode(currentNode.label); 13 | RandomListNode nextNode = currentNode.next; 14 | currentNode.next = cloneNode; 15 | cloneNode.next = nextNode; 16 | currentNode = nextNode; 17 | } 18 | currentNode = pHead; 19 | //2、重新遍历链表,复制老结点的随机指针给新结点,如 A1.random = A.random.next; 20 | while (currentNode != null) { 21 | currentNode.next.random = currentNode.random == null ? null : currentNode.random.next; 22 | currentNode = currentNode.next.next; 23 | } 24 | //3、拆分链表,将链表拆分为原链表和复制后的链表 25 | currentNode = pHead; 26 | RandomListNode pCloneHead = pHead.next; 27 | while (currentNode != null) { 28 | RandomListNode cloneNode = currentNode.next; 29 | // 恢复出原始结点的 next 指向 30 | currentNode.next = cloneNode.next; 31 | // 除了最后一个克隆的结点,其余克隆结点都有下一个结点的下一个结点,所以这里要做空指针判断 32 | cloneNode.next = cloneNode.next == null ? null : cloneNode.next.next; 33 | currentNode = currentNode.next; 34 | } 35 | return pCloneHead; 36 | } 37 | 38 | 39 | public static void main(String[] args) { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /codes/java/35/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | import java.util.Set; 4 | 5 | /** 6 | * 使用 Hash 表的方式 7 | * 8 | * @author liwei 9 | */ 10 | public class Solution3 { 11 | public RandomListNode Clone(RandomListNode pHead) { 12 | Map map = new HashMap<>(); 13 | RandomListNode curNode = pHead; 14 | // 体会这里设置虚拟头结点的必要性 15 | RandomListNode dummyNode = new RandomListNode(-1); 16 | RandomListNode p = dummyNode; 17 | // 完成复制 next 结点,并且将对应关系放入 Hash 表 18 | while (curNode != null) { 19 | RandomListNode newNode = new RandomListNode(curNode.label); 20 | map.put(curNode, newNode); 21 | curNode = curNode.next; 22 | p.next = newNode; 23 | p = newNode; 24 | } 25 | // 完成复制链表的 random 指针的赋值 26 | Set> entrySet = map.entrySet(); 27 | for (Map.Entry entry : entrySet) { 28 | entry.getValue().random = map.get(entry.getKey().random); 29 | } 30 | return dummyNode.next; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /codes/java/35/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | // Python 写法能够通过 4 | // class Solution: 5 | // # 返回 RandomListNode 6 | // def Clone(self, pHead): 7 | // # write code here 8 | // if not pHead: return 9 | // newNode = RandomListNode(pHead.label) 10 | // newNode.random = pHead.random 11 | // newNode.next = self.Clone(pHead.next) 12 | // return newNode 13 | 14 | // 不能通过 15 | public RandomListNode Clone(RandomListNode pHead) { 16 | if (pHead == null) { 17 | return null; 18 | } 19 | RandomListNode p = new RandomListNode(pHead.label); 20 | p.next = pHead.next; 21 | p.random = pHead.random; 22 | if(pHead.next!=null){ 23 | p.next = Clone(pHead.next); 24 | } 25 | return p; 26 | } 27 | 28 | 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /codes/java/36/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val = 0; 3 | TreeNode left = null; 4 | TreeNode right = null; 5 | 6 | public TreeNode(int val) { 7 | this.val = val; 8 | } 9 | } 10 | 11 | public class Solution { 12 | 13 | private TreeNode linkedListTail; 14 | private TreeNode res; 15 | 16 | public TreeNode Convert(TreeNode pRootOfTree) { 17 | convert(pRootOfTree); 18 | return res; 19 | } 20 | 21 | /** 22 | * 中序遍历 23 | * 24 | * @param root 25 | */ 26 | private void convert(TreeNode root) { 27 | if (root == null) { 28 | return; 29 | } 30 | convert(root.left); 31 | // 中序遍历真正做事情的地方 32 | if (linkedListTail == null) { // 对应刚开始的时候 33 | linkedListTail = root; 34 | // 在最左边的地方记录需要返回的双向链表的根结点 35 | res = root; 36 | } else { 37 | linkedListTail.right = root; 38 | root.left = linkedListTail; 39 | linkedListTail = root; 40 | } 41 | convert(root.right); 42 | } 43 | } -------------------------------------------------------------------------------- /codes/java/36/src/Solution2.java: -------------------------------------------------------------------------------- 1 | 2 | public class Solution2 { 3 | public TreeNode convert(TreeNode root) { 4 | if (root == null) { 5 | return root; 6 | } 7 | TreeNode left = rightMost(root.left); 8 | TreeNode right = leftMost(root.right); 9 | convert(root.left); 10 | convert(root.right); 11 | if (left != null) { 12 | left.right = root; 13 | } 14 | root.left = left; 15 | if (right != null) { 16 | right.left = root; 17 | } 18 | root.right = right; 19 | while (root.left != null) { 20 | root = root.left; 21 | } 22 | return root; 23 | } 24 | 25 | TreeNode leftMost(TreeNode root) { 26 | if (root == null) { 27 | return null; 28 | } 29 | while (root.left != null) { 30 | root = root.left; 31 | } 32 | return root; 33 | } 34 | 35 | TreeNode rightMost(TreeNode root) { 36 | if (root == null) { 37 | return null; 38 | } 39 | while (root.right != null) { 40 | root = root.right; 41 | } 42 | return root; 43 | } 44 | } -------------------------------------------------------------------------------- /codes/java/37/src/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/18 上午7:36 4 | */ 5 | 6 | class Student{ 7 | private String name; 8 | private int age; 9 | 10 | public String getName() { 11 | return name; 12 | } 13 | 14 | public void setName(String name) { 15 | this.name = name; 16 | } 17 | 18 | public int getAge() { 19 | return age; 20 | } 21 | 22 | public void setAge(int age) { 23 | this.age = age; 24 | } 25 | } 26 | 27 | public class Main { 28 | 29 | public static void main(String[] args) { 30 | Student s = null; 31 | hello(s); 32 | System.out.println(s==null); 33 | } 34 | 35 | private static void hello(Student s){ 36 | if(s==null){ 37 | s = new Student(); 38 | s.setName("liwei"); 39 | s.setAge(24); 40 | } 41 | System.out.println(s==null); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /codes/java/38/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.Stack; 4 | 5 | /** 6 | * 使用标准的递归回溯的解法 7 | * 8 | * @author liwei 9 | */ 10 | public class Solution { 11 | 12 | private boolean[] marked; 13 | private ArrayList res; 14 | 15 | public ArrayList Permutation(String str) { 16 | res = new ArrayList<>(); 17 | int len = str.length(); 18 | if (len == 0) { 19 | return res; 20 | } 21 | marked = new boolean[len]; 22 | char[] charArr = str.toCharArray(); 23 | 24 | Arrays.sort(charArr); 25 | 26 | StringBuilder stringBuilder = new StringBuilder(); 27 | for (int i = 0; i < len; i++) { 28 | stringBuilder.append(charArr[i]); 29 | } 30 | Stack pre = new Stack<>(); 31 | findPermutation(stringBuilder.toString(), 0, len, pre); 32 | return res; 33 | } 34 | 35 | private void findPermutation(String str, int hasUsedCount, int len, Stack pre) { 36 | if (hasUsedCount == len) { 37 | StringBuilder stringBuilder = new StringBuilder(); 38 | for (int i = 0; i < len; i++) { 39 | stringBuilder.append(pre.get(i)); 40 | } 41 | res.add(stringBuilder.toString()); 42 | return; 43 | } 44 | for (int i = 0; i < len; i++) { 45 | if (!marked[i]) { 46 | if (i > 0 && str.charAt(i) == str.charAt(i - 1) && !marked[i - 1]) { 47 | continue; 48 | } 49 | marked[i] = true; 50 | pre.add(str.charAt(i)); 51 | findPermutation(str, hasUsedCount + 1, len, pre); 52 | pre.pop(); 53 | marked[i] = false; 54 | } 55 | } 56 | } 57 | 58 | public static void main(String[] args) { 59 | Solution solution = new Solution(); 60 | ArrayList permutation = solution.Permutation("aba"); 61 | System.out.println(permutation); 62 | } 63 | } -------------------------------------------------------------------------------- /codes/java/38/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.Collections; 4 | 5 | /** 6 | * 采用书上说的交换的解法 7 | * 这种做法没有去重 8 | */ 9 | public class Solution2 { 10 | 11 | public ArrayList Permutation(String str) { 12 | ArrayList res = new ArrayList<>(); 13 | int len = str.length(); 14 | if (len == 0) { 15 | return res; 16 | } 17 | char[] chars = str.toCharArray(); 18 | findPermutation(chars, 0, len, res); 19 | // 这一步排序其实是没有必要的,只是为了通过 online judge 20 | Collections.sort(res); 21 | return res; 22 | } 23 | 24 | private void findPermutation(char[] chars, int begin, int len, ArrayList res) { 25 | if (begin == len - 1) { 26 | String s = String.valueOf(chars); 27 | // 在这一步去重,以 28 | if(!res.contains(s)){ 29 | res.add(s); 30 | } 31 | return; 32 | } 33 | for (int i = begin; i < len; i++) { 34 | swap(chars, begin, i); 35 | findPermutation(chars, begin + 1, len, res); 36 | swap(chars, begin, i); 37 | } 38 | } 39 | 40 | private void swap(char[] arr, int index1, int index2) { 41 | if (index1 == index2) { 42 | return; 43 | } 44 | char temp = arr[index1]; 45 | arr[index1] = arr[index2]; 46 | arr[index2] = temp; 47 | } 48 | 49 | public static void main(String[] args) { 50 | Solution2 solution2 = new Solution2(); 51 | ArrayList permutation = solution2.Permutation("aac"); 52 | System.out.println(permutation); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /codes/java/39/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | // 5 | // {1,2,3,2,2,2,5,4,2} 9 4 6 | // {1,2,3,2,2,2,5,4} 8 4 7 | public int MoreThanHalfNum_Solution(int[] array) { 8 | int len = array.length; 9 | if (len == 0) { 10 | return 0; 11 | } 12 | Arrays.sort(array); 13 | int target = array[len / 2]; 14 | int count = 0; 15 | for (int i = 0; i < len; i++) { 16 | if (array[i] == target) { 17 | count++; 18 | } 19 | } 20 | if (count > len / 2) { 21 | return target; 22 | } 23 | return 0; 24 | } 25 | 26 | 27 | public static void main(String[] args) { 28 | int[] nums = new int[]{1, 2, 3, 2, 2, 2, 5, 4, 2}; 29 | // [1,2,3,2,4,2,5,2,3] 30 | Solution solution = new Solution(); 31 | int moreThanHalfNum_solution = solution.MoreThanHalfNum_Solution(nums); 32 | System.out.println(moreThanHalfNum_solution); 33 | } 34 | } -------------------------------------------------------------------------------- /codes/java/4/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean Find(int target, int[][] array) { 4 | int row = array.length; 5 | if (row == 0) { 6 | return false; 7 | } 8 | int col = array[0].length; 9 | 10 | // 从左下角开始查找 11 | int i = row - 1; 12 | 13 | // 这一行代码还可以位于下面这个注释中,但是在这个位置效率更高,也应该在这个位置,j 没有必要重置 14 | // 这一行代码还可以位于下面这个注释中,但是在这个位置效率更高,也应该在这个位置,j 没有必要重置 15 | // 这一行代码还可以位于下面这个注释中,但是在这个位置效率更高,也应该在这个位置,j 没有必要重置 16 | int j = 0; 17 | 18 | // 从最后一行开始,一点一点去匹配,遇到比 19 | while (i >= 0) { 20 | // int j = 0; 21 | while (j < col && array[i][j] < target) { 22 | j++; 23 | } 24 | if (j < col && array[i][j] == target) { 25 | return true; 26 | } 27 | i--; 28 | } 29 | return false; 30 | } 31 | 32 | public static void main(String[] args) { 33 | int[][] matrix = new int[][]{ 34 | {1, 2, 8, 9}, 35 | {2, 4, 9, 12}, 36 | {4, 7, 10, 13}, 37 | {6, 8, 11, 15} 38 | }; 39 | Solution solution = new Solution(); 40 | boolean find = solution.Find(16, matrix); 41 | System.out.println(find); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /codes/java/40/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | public class Solution { 4 | public ArrayList GetLeastNumbers_Solution(int[] input, int k) { 5 | ArrayList res = new ArrayList<>(); 6 | int len = input.length; 7 | if (len == 0 || k < 0 || k > len) { 8 | return res; 9 | } 10 | int l = 0; 11 | int r = len - 1; 12 | // 考虑边界条件 13 | while (l <= r) { 14 | int partition = partition(input, l, r); 15 | if (partition < k - 1) { 16 | l = partition + 1; 17 | } else if (partition > k - 1) { 18 | r = partition - 1; 19 | } else { 20 | assert partition == k - 1; 21 | for (int i = 0; i < k; i++) { 22 | res.add(input[i]); 23 | } 24 | break; 25 | } 26 | } 27 | return res; 28 | } 29 | 30 | private int partition(int[] nums, int l, int r) { 31 | // 可以随机选取 32 | int pivot = nums[l]; 33 | int lt = l; 34 | for (int i = l + 1; i <= r; i++) { 35 | if (nums[i] < pivot) { 36 | lt++; 37 | swap(nums, lt, i); 38 | } 39 | } 40 | swap(nums, lt, l); 41 | return lt; 42 | } 43 | 44 | private void swap(int[] nums, int index1, int index2) { 45 | if (index1 == index2) { 46 | return; 47 | } 48 | int temp = nums[index1]; 49 | nums[index1] = nums[index2]; 50 | nums[index2] = temp; 51 | } 52 | 53 | public static void main(String[] args) { 54 | int[] nums = new int[]{4, 5, 1, 6, 2, 7, 3, 8}; 55 | int k = 8; 56 | Solution solution = new Solution(); 57 | ArrayList getLeastNumbers_solution = solution.GetLeastNumbers_Solution(nums, k); 58 | System.out.println(getLeastNumbers_solution); 59 | } 60 | } -------------------------------------------------------------------------------- /codes/java/42/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int FindGreatestSumOfSubArray(int[] array) { 4 | int n = array.length; 5 | if (n == 0) { 6 | return 0; 7 | } 8 | int[] dp = new int[n]; 9 | dp[0] = array[0]; 10 | int res = array[0]; 11 | for (int i = 1; i < n; i++) { 12 | dp[i] = Integer.max(dp[i - 1] + array[i], array[i]); 13 | res = Integer.max(res, dp[i]); 14 | } 15 | return res; 16 | } 17 | 18 | public static void main(String[] args) { 19 | int[] nums = new int[]{6, -3, -2, 7, -15, 1, 2, 2}; 20 | Solution solution = new Solution(); 21 | int findGreatestSumOfSubArray = solution.FindGreatestSumOfSubArray(nums); 22 | System.out.println(findGreatestSumOfSubArray); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /codes/java/45/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Comparator; 3 | 4 | public class Solution { 5 | public String PrintMinNumber(int[] numbers) { 6 | int len = numbers.length; 7 | if (len == 0) { 8 | return ""; 9 | } 10 | if (len == 1) { 11 | return numbers[0] + ""; 12 | } 13 | Comparator comparator = new Comparator() { 14 | @Override 15 | public int compare(String o1, String o2) { 16 | String a = o1 + o2; 17 | String b = o2 + o1; 18 | int len = a.length(); 19 | for (int i = 0; i < len ; i++) { 20 | if(a.charAt(i)b.charAt(i)){ 23 | return 1; 24 | } 25 | } 26 | return 0; 27 | } 28 | }; 29 | String[] numsStr = new String[len]; 30 | for (int i = 0; i < len; i++) { 31 | numsStr[i] = numbers[i] + ""; 32 | } 33 | Arrays.sort(numsStr, comparator); 34 | StringBuilder stringBuilder = new StringBuilder(); 35 | for (int i = 0; i < len; i++) { 36 | stringBuilder.append(numsStr[i]); 37 | } 38 | return stringBuilder.toString(); 39 | } 40 | 41 | public static void main(String[] args) { 42 | int[] nums = new int[]{3, 32, 321}; 43 | Solution solution = new Solution(); 44 | String printMinNumber = solution.PrintMinNumber(nums); 45 | System.out.println(printMinNumber); 46 | } 47 | } -------------------------------------------------------------------------------- /codes/java/45/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution2 { 4 | /** 5 | * 在 Solution 的基础上精简了一下,使得代码不要那么长,其实思路是一样的 6 | * 7 | * @param numbers 8 | * @return 9 | */ 10 | public String PrintMinNumber(int[] numbers) { 11 | int len = numbers.length; 12 | if (len == 0) { 13 | return ""; 14 | } 15 | String[] numsStr = new String[len]; 16 | for (int i = 0; i < len; i++) { 17 | numsStr[i] = numbers[i] + ""; 18 | } 19 | Arrays.sort(numsStr, (a, b) -> (a + b).compareTo(b + a)); 20 | StringBuilder builder = new StringBuilder(); 21 | for (int i = 0; i < len; i++) { 22 | builder.append(numsStr[i]); 23 | } 24 | return builder.toString(); 25 | } 26 | 27 | public static void main(String[] args) { 28 | int[] nums = new int[]{3, 32, 321}; 29 | Solution2 solution = new Solution2(); 30 | String printMinNumber = solution.PrintMinNumber(nums); 31 | System.out.println(printMinNumber); 32 | } 33 | } -------------------------------------------------------------------------------- /codes/java/47/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int getMaxValue(int[][] matrix) { 4 | int row = matrix.length; 5 | if (row == 0) { 6 | return 0; 7 | } 8 | int col = matrix[0].length; 9 | int[][] dp = new int[row][col]; 10 | dp[0][0] = matrix[0][0]; 11 | 12 | for (int j = 1; j < col; j++) { 13 | dp[0][j] = dp[0][j - 1] + matrix[0][j]; 14 | } 15 | for (int i = 1; i < row; i++) { 16 | dp[i][0] = dp[i - 1][0] + matrix[i][0]; 17 | for (int j = 1; j < col; j++) { 18 | dp[i][j] = Integer.max(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j]; 19 | } 20 | } 21 | return dp[row - 1][col - 1]; 22 | } 23 | 24 | public static void main(String[] args) { 25 | int[][] matrix = new int[][]{ 26 | {1, 10, 3, 8}, 27 | {12, 2, 9, 6}, 28 | {5, 7, 4, 11}, 29 | {3, 7, 16, 5} 30 | }; 31 | Solution solution = new Solution(); 32 | int maxValue = solution.getMaxValue(matrix); 33 | System.out.println(maxValue); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /codes/java/47/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int getMaxValue(int[][] matrix) { 4 | int row = matrix.length; 5 | if (row == 0) { 6 | return 0; 7 | } 8 | int col = matrix[0].length; 9 | int[] dp = new int[col]; 10 | dp[0] = matrix[0][0]; 11 | 12 | for (int j = 1; j < col; j++) { 13 | dp[j] = dp[j - 1] + matrix[0][j]; 14 | } 15 | for (int i = 1; i < row; i++) { 16 | dp[0] = dp[0] + matrix[i][0]; 17 | for (int j = 1; j < col; j++) { 18 | dp[j] = Integer.max(dp[j], dp[j - 1]) + matrix[i][j]; 19 | } 20 | } 21 | return dp[col - 1]; 22 | } 23 | 24 | public static void main(String[] args) { 25 | int[][] matrix = new int[][]{ 26 | {1, 10, 3, 8}, 27 | {12, 2, 9, 6}, 28 | {5, 7, 4, 11}, 29 | {3, 7, 16, 5} 30 | }; 31 | Solution2 solution2 = new Solution2(); 32 | int maxValue = solution2.getMaxValue(matrix); 33 | System.out.println(maxValue); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /codes/java/47/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int getMaxValue(int[][] matrix) { 4 | int row = matrix.length; 5 | if (row == 0) { 6 | return 0; 7 | } 8 | int col = matrix[0].length; 9 | int[] dp = new int[col]; 10 | for (int i = 0; i < row; i++) { 11 | for (int j = 0; j < col; j++) { 12 | dp[j] = Integer.max(dp[j], j - 1 < 0 ? 0 : dp[j - 1]) + matrix[i][j]; 13 | } 14 | } 15 | return dp[col - 1]; 16 | } 17 | 18 | public static void main(String[] args) { 19 | int[][] matrix = new int[][]{ 20 | {1, 10, 3, 8}, 21 | {12, 2, 9, 6}, 22 | {5, 7, 4, 11}, 23 | {3, 7, 16, 5} 24 | }; 25 | Solution3 solution3 = new Solution3(); 26 | int maxValue = solution3.getMaxValue(matrix); 27 | System.out.println(maxValue); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /codes/java/49/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 求丑数 3 | */ 4 | public class Solution { 5 | 6 | private boolean isUgly(int number) { 7 | while (number % 2 == 0) { 8 | number /= 2; 9 | } 10 | while (number % 3 == 0) { 11 | number /= 3; 12 | } 13 | while (number % 5 == 0) { 14 | number /= 5; 15 | } 16 | return number == 1; 17 | } 18 | 19 | public int getUglyNumber(int index) { 20 | if (index <= 0) { 21 | return 0; 22 | } 23 | int count = 0; 24 | int n = 0; 25 | while (count < index) { 26 | n++; 27 | if (isUgly(n)) { 28 | count++; 29 | } 30 | } 31 | return n; 32 | } 33 | 34 | public static void main(String[] args) { 35 | Solution solution = new Solution(); 36 | for (int i = 1; i <=15 ; i++) { 37 | int getUglyNumberSolution = solution.getUglyNumber(i); 38 | System.out.printf("%s ",getUglyNumberSolution); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /codes/java/49/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 求丑数,讨论去提供的解法,和书上的思路是一样的 3 | */ 4 | public class Solution2 { 5 | 6 | // 1、2、3、4、5、6 都是丑数 7 | public int GetUglyNumber_Solution(int index) { 8 | if (index < 7) { 9 | return index; 10 | } 11 | 12 | // 状态的定义:第 i 个丑数的最小值,从 0 开始计算 13 | int[] dp = new int[index]; 14 | dp[0] = 1; 15 | 16 | int t2 = 0; 17 | int t3 = 0; 18 | int t5 = 0; 19 | 20 | // 注意: i 从 1 开始 21 | for (int i = 1; i < index; i++) { 22 | dp[i] = min3(dp[t2] * 2, dp[t3] * 3, dp[t5] * 5); 23 | if (dp[i] == dp[t2] * 2) { 24 | t2++; 25 | } 26 | if (dp[i] == dp[t3] * 3) { 27 | t3++; 28 | } 29 | if (dp[i] == dp[t5] * 5) { 30 | t5++; 31 | } 32 | } 33 | // System.out.println(Arrays.toString(dp)); 34 | return dp[index - 1]; 35 | } 36 | 37 | private int min3(int n1, int n2, int n3) { 38 | return Integer.min(Integer.min(n1, n2), n3); 39 | } 40 | 41 | public static void main(String[] args) { 42 | Solution2 solution2 = new Solution2(); 43 | // 1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 44 | // [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] 45 | int getUglyNumberSolution = solution2.GetUglyNumber_Solution(15); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /codes/java/5/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public String replaceSpace(StringBuffer str) { 4 | int len = str.length(); 5 | if (len == 0) { 6 | return ""; 7 | } 8 | StringBuilder stringBuilder = new StringBuilder(); 9 | for (int i = 0; i < len; i++) { 10 | char c = str.charAt(i); 11 | if (c == ' ') { 12 | stringBuilder.append("%20"); 13 | } else { 14 | stringBuilder.append(c); 15 | } 16 | } 17 | return stringBuilder.toString(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /codes/java/5/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/14 上午9:21 4 | */ 5 | public class Solution2 { 6 | 7 | public String replaceSpace(StringBuffer str) { 8 | return str.toString().replaceAll("\\s", "%20"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /codes/java/51/src/BFSolution.java: -------------------------------------------------------------------------------- 1 | public class BFSolution { 2 | 3 | /** 4 | * 暴力解法求逆序对,使用两种循环进行枚举,时间复杂度:O(n^2) 5 | * 6 | * @param nums 7 | */ 8 | public int inversionPairs(int[] nums) { 9 | int count = 0; 10 | for (int i = 0; i < nums.length - 1; i++) { 11 | for (int j = i + 1; j < nums.length; j++) { 12 | if (nums[i] > nums[j]) { 13 | System.out.println("找到的逆序对之一:" + nums[i] + " " + nums[j]); 14 | count++; 15 | } 16 | } 17 | } 18 | return count; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /codes/java/51/src/TestCase.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class TestCase { 4 | 5 | 6 | public static void main(String[] args) { 7 | int[] nums = new int[]{7, 5, 6, 4}; 8 | int[] nums1 = new int[]{7, 5, 6, 4}; 9 | 10 | 11 | BFSolution bfSolution = new BFSolution(); 12 | 13 | Solution2 solution2 = new Solution2(); 14 | 15 | System.out.println(bfSolution.inversionPairs(nums)); 16 | System.out.println(solution2.inversionPairs(nums1)); 17 | 18 | System.out.println(Arrays.toString(nums1)); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /codes/java/51_1/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 暴力解法 3 | */ 4 | public class Solution3 { 5 | 6 | public int InversePairs(int[] array) { 7 | int count = 0; 8 | int len = array.length; 9 | if (len == 0) { 10 | return 0; 11 | } 12 | 13 | for (int i = 0; i < len - 1; i++) { 14 | for (int j = i + 1; j < len; j++) { 15 | if (array[i] > array[j]) { 16 | count++; 17 | } 18 | } 19 | } 20 | return count; 21 | } 22 | 23 | public static void main(String[] args) { 24 | int[] nums = new int[]{1, 2, 3, 4, 5, 6, 7, 0}; 25 | Solution3 solution3 = new Solution3(); 26 | int inversePairs = solution3.InversePairs(nums); 27 | System.out.println(inversePairs); 28 | 29 | nums = new int[]{7, 5, 6, 4}; 30 | solution3 = new Solution3(); 31 | inversePairs = solution3.InversePairs(nums); 32 | System.out.println(inversePairs); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /codes/java/51_1/src/TestCase.java: -------------------------------------------------------------------------------- 1 | import java.util.Random; 2 | 3 | public class TestCase { 4 | 5 | private static Random random = new Random(System.currentTimeMillis()); 6 | 7 | private static int[] generateRandomArray() { 8 | int len = 10; 9 | int[] randomArray = new int[len]; 10 | for (int i = 0; i < len; i++) { 11 | int randomInt = random.nextInt(50); 12 | randomArray[i] = randomInt; 13 | } 14 | return randomArray; 15 | } 16 | 17 | public static void main(String[] args) { 18 | 19 | for (int i = 0; i < 5; i++) { 20 | int[] randomArray = generateRandomArray(); 21 | int[] randomArray2 = randomArray.clone(); 22 | int[] randomArray3 = randomArray.clone(); 23 | Solution solution = new Solution(); 24 | Solution2 solution2 = new Solution2(); 25 | Solution3 solution3 = new Solution3(); 26 | int inversePairs1 = solution.InversePairs(randomArray); 27 | int inversePairs2 = solution2.InversePairs(randomArray2); 28 | int inversePairs3 = solution3.InversePairs(randomArray3); 29 | System.out.println(inversePairs1 + "\t" + inversePairs2 + "\t" + inversePairs3); 30 | if(inversePairs1!=inversePairs2 || inversePairs1!=inversePairs3 || inversePairs2!=inversePairs3){ 31 | System.out.println("算法错误!"); 32 | } 33 | } 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /codes/java/52/src/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | 3 | public static void main(String[] args) { 4 | 5 | 6 | int num = 10; 7 | 8 | System.out.println(num >>> 2); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /codes/java/54/src/Solution.java: -------------------------------------------------------------------------------- 1 | 2 | // 第 54 题:二叉搜索数中第 k 大节点 3 | public class Solution { 4 | 5 | public static void main(String[] args) { 6 | // write your code here 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /codes/java/54/src/Solution2.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | public class Solution2 { 4 | 5 | TreeNode res; 6 | private int k; 7 | 8 | // 中序遍历 9 | TreeNode KthNode(TreeNode pRoot, int k) { 10 | if (k <= 0 || pRoot == null) { 11 | return null; 12 | } 13 | this.k = k; 14 | inOrder(pRoot); 15 | return res; 16 | } 17 | 18 | void inOrder(TreeNode node) { 19 | if (node == null) { 20 | return; 21 | } 22 | inOrder(node.left); 23 | k--; 24 | if (k == 0) { 25 | res = node; 26 | return; 27 | } 28 | inOrder(node.right); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /codes/java/54/src/Solution3.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val = 0; 3 | TreeNode left = null; 4 | TreeNode right = null; 5 | 6 | public TreeNode(int val) { 7 | this.val = val; 8 | 9 | } 10 | 11 | } 12 | 13 | public class Solution { 14 | 15 | TreeNode res; 16 | 17 | // 中序遍历 18 | TreeNode KthNode(TreeNode pRoot, int k) { 19 | if (k <= 0 || pRoot == null) { 20 | return null; 21 | } 22 | int[] arr = new int[1]; 23 | arr[0] = k; 24 | inOrder(pRoot, arr); 25 | return res; 26 | } 27 | 28 | void inOrder(TreeNode node, int[] k) { 29 | if (node == null) { 30 | return; 31 | } 32 | inOrder(node.left, k); 33 | k[0]--; 34 | if (k[0] == 0) { 35 | res = node; 36 | return; 37 | } 38 | inOrder(node.right, k); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /codes/java/55/src/Solution2.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val = 0; 3 | TreeNode left = null; 4 | TreeNode right = null; 5 | 6 | public TreeNode(int val) { 7 | this.val = val; 8 | 9 | } 10 | } 11 | 12 | public class Solution { 13 | public int TreeDepth(TreeNode root) { 14 | if (root == null) { 15 | return 0; 16 | } 17 | return Integer.max(TreeDepth(root.left), TreeDepth(root.right)) + 1; 18 | } 19 | } -------------------------------------------------------------------------------- /codes/java/55_2_IsBalanced/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | public class Solution { 12 | public boolean IsBalanced_Solution(TreeNode root) { 13 | int[] depth = new int[1]; 14 | return isBalanced(root, depth); 15 | } 16 | 17 | private boolean isBalanced(TreeNode root, int[] depth) { 18 | if (root == null) { 19 | depth[0] = 0; 20 | return true; 21 | } 22 | int[] left = new int[1]; 23 | int[] right = new int[1]; 24 | // 满足左子树右子树是平衡二叉树的时候,才去计算它们的高度差 25 | if (isBalanced(root.left, left) && isBalanced(root.right, right)) { 26 | if (Math.abs(left[0] - right[0]) <= 1) { 27 | depth[0] = Integer.max(left[0], right[0]) + 1; 28 | return true; 29 | } 30 | } 31 | return false; 32 | } 33 | } -------------------------------------------------------------------------------- /codes/java/58/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | /** 4 | * 辅助函数:翻转字符数组指定区间内的字符 5 | * 6 | * @param str 7 | * @param start 8 | * @param end 9 | */ 10 | private void reverseString(char[] str, int start, int end) { 11 | int l = start; 12 | int r = end; 13 | while (l < r) { 14 | swap(str, l, r); 15 | l++; 16 | r--; 17 | } 18 | } 19 | 20 | /** 21 | * 辅助函数:交换字符数组指定索引的字符 22 | * 23 | * @param str 24 | * @param index1 25 | * @param index2 26 | */ 27 | private void swap(char[] str, int index1, int index2) { 28 | if (index1 == index2) { 29 | return; 30 | } 31 | char temp = str[index1]; 32 | str[index1] = str[index2]; 33 | str[index2] = temp; 34 | } 35 | 36 | public String ReverseSentence(String str) { 37 | int len = str.length(); 38 | if (len == 0 || len == 1) { 39 | return str; 40 | } 41 | char[] charArr = str.toCharArray(); 42 | reverseString(charArr, 0, len - 1); 43 | int start = 0; 44 | for (int i = 0; i < len; i++) { 45 | if (charArr[i] == ' ') { 46 | reverseString(charArr, start, i - 1); 47 | start = i + 1; 48 | } 49 | } 50 | // 最后还要记得反转一下 51 | reverseString(charArr, start, len - 1); 52 | return String.valueOf(charArr); 53 | } 54 | 55 | public static void main(String[] args) { 56 | String str = "write your code here"; 57 | Solution solution = new Solution(); 58 | String reverseSentence = solution.ReverseSentence(str); 59 | System.out.println(reverseSentence); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /codes/java/58_2/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * https://www.nowcoder.com/practice/12d959b108cb42b1ab72cef4d36af5ec?tpId=13&tqId=11196&tPage=3&rp=3&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 3 | * 左旋转字符串 4 | * 5 | * @author liwei 6 | */ 7 | public class Solution { 8 | 9 | private void reverseString(char[] charArr, int start, int end) { 10 | int l = start; 11 | int r = end; 12 | while (l < r) { 13 | swap(charArr, l, r); 14 | l++; 15 | r--; 16 | } 17 | } 18 | 19 | private void swap(char[] charArr, int index1, int index2) { 20 | if (index1 == index2) { 21 | return; 22 | } 23 | char temp = charArr[index1]; 24 | charArr[index1] = charArr[index2]; 25 | charArr[index2] = temp; 26 | } 27 | 28 | public String LeftRotateString(String str, int n) { 29 | int len = str.length(); 30 | if (len == 0 || n < 0) { 31 | return ""; 32 | } 33 | if (len == 1) { 34 | return str; 35 | } 36 | 37 | // 这里要注意了 38 | n = len - n % len; 39 | 40 | char[] charArr = str.toCharArray(); 41 | reverseString(charArr, 0, len - 1); 42 | reverseString(charArr, 0, n - 1); 43 | reverseString(charArr, n, len - 1); 44 | return String.valueOf(charArr); 45 | } 46 | 47 | public static void main(String[] args) { 48 | String str = "abcXYZdef"; 49 | Solution solution = new Solution(); 50 | String leftRotateString = solution.LeftRotateString(str, 3); 51 | System.out.println(leftRotateString); 52 | } 53 | } -------------------------------------------------------------------------------- /codes/java/6/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Stack; 3 | 4 | class ListNode { 5 | int val; 6 | ListNode next = null; 7 | 8 | ListNode(int val) { 9 | this.val = val; 10 | } 11 | } 12 | 13 | public class Solution { 14 | public ArrayList printListFromTailToHead(ListNode listNode) { 15 | ArrayList res = new ArrayList<>(); 16 | if (listNode == null) { 17 | return res; 18 | } 19 | Stack stack = new Stack<>(); 20 | ListNode curNode = listNode; 21 | while (curNode != null) { 22 | stack.add(curNode.val); 23 | curNode = curNode.next; 24 | } 25 | while (!stack.isEmpty()) { 26 | res.add(stack.pop()); 27 | } 28 | return res; 29 | } 30 | } -------------------------------------------------------------------------------- /codes/java/6/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | /** 4 | * 递归写法 5 | * 6 | * @author liwei 7 | */ 8 | public class Solution2 { 9 | public ArrayList printListFromTailToHead(ListNode listNode) { 10 | ArrayList res = new ArrayList<>(); 11 | if (listNode == null) { 12 | return res; 13 | } 14 | printListFromTailToHead(listNode, res); 15 | return res; 16 | } 17 | 18 | private void printListFromTailToHead(ListNode listNode, ArrayList res) { 19 | if (listNode == null) { 20 | return; 21 | } 22 | // 写在这个位置,就是正序 23 | if (listNode.next != null) { 24 | printListFromTailToHead(listNode.next, res); 25 | } 26 | // 写在这个位置,就是倒序 27 | res.add(listNode.val); 28 | } 29 | } -------------------------------------------------------------------------------- /codes/java/61/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | 5 | public boolean isContinuous(int[] numbers) { 6 | int len = numbers.length; 7 | if (len != 5) { 8 | return false; 9 | } 10 | Arrays.sort(numbers); 11 | // "0" 的个数 12 | int zeroCount = 0; 13 | // 当前数与后一个数的距离,距离为 1,表示是顺子 14 | int diffDistance = 0; 15 | for (int i = 0; i < 4; i++) { 16 | if (numbers[i] == 0) { 17 | zeroCount++; 18 | continue; 19 | } 20 | if (numbers[i] == numbers[i + 1]) { 21 | return false; 22 | } else { 23 | diffDistance += (numbers[i + 1] - numbers[i] - 1); 24 | } 25 | 26 | } 27 | return zeroCount >= diffDistance; 28 | } 29 | } -------------------------------------------------------------------------------- /codes/java/62/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | 3 | public class Solution { 4 | // 约瑟夫环问题 5 | // 其实并不一定要构造出一个真的循环链表 6 | public int LastRemaining_Solution(int n, int m) { 7 | // 先处理极端输入 8 | if (n <= 1) { 9 | return -1; 10 | } 11 | // 这里用链表是为了提升性能,如果用 ArrayList 在删除操作中,就会有大量的性能消耗 12 | LinkedList list = new LinkedList<>(); 13 | int bt = 0; 14 | for (int i = 0; i < n; i++) { 15 | list.addLast(i); 16 | } 17 | while (list.size() > 1) { 18 | // 表示的是索引的值 19 | bt = (bt + m - 1) % list.size(); 20 | // 下面这一行代码可以帮助调试 21 | // System.out.println(bt + " " + list); 22 | // bt 是链表的索引 23 | list.remove(bt); 24 | } 25 | // 思考为什么会有最后这个判断 26 | return list.get(0); 27 | } 28 | 29 | // 测试用例: n = 6,[0,1,2,3,4,5],m=3 30 | public static void main(String[] args) { 31 | Solution solution = new Solution(); 32 | int n = 6; 33 | int m = 3; 34 | int lastRemainingSolution = solution.LastRemaining_Solution(n, m); 35 | System.out.println(lastRemainingSolution); 36 | } 37 | } -------------------------------------------------------------------------------- /codes/java/64/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int Sum_Solution(int n) { 4 | if (n <= 0) { 5 | return 0; 6 | } 7 | return n + Sum_Solution(n - 1); 8 | } 9 | 10 | public int Sum_Solution2(int n) { 11 | int sum = 0; 12 | for (int i = 0; i <= n; i++) { 13 | sum += i; 14 | } 15 | return sum; 16 | } 17 | 18 | public int Sum_Solution3(int n) { 19 | int sum = n; 20 | boolean ans = n > 0 && ((sum += Sum_Solution(n - 1)) > 0); 21 | return sum; 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution solution = new Solution(); 26 | int n = 100; 27 | int solution1 = solution.Sum_Solution(n); 28 | System.out.println(solution1); 29 | int solution2 = solution.Sum_Solution2(n); 30 | System.out.println(solution2); 31 | if (solution1 != solution2) { 32 | System.out.println("程序错误"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /codes/java/65/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int Add(int num1, int num2) { 4 | int sum = 0; 5 | while (true) { 6 | sum = num1 ^ num2; 7 | int carry = num1 & num2; 8 | if (carry == 0) { 9 | break; 10 | } 11 | num1 = sum; 12 | num2 = carry << 1; 13 | 14 | } 15 | return sum; 16 | } 17 | 18 | public static void main(String[] args) { 19 | Solution solution = new Solution(); 20 | int add = solution.Add(14, 15); 21 | System.out.println(add); 22 | } 23 | } -------------------------------------------------------------------------------- /codes/java/65/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/19 下午1:45 4 | */ 5 | public class Solution2 { 6 | 7 | // 书上的写法 8 | public int Add(int num1, int num2) { 9 | int sum = 0; 10 | int carry = 0; 11 | do { 12 | sum = num1 ^ num2; 13 | carry = num1 & num2; 14 | 15 | num1 = sum; 16 | num2 = carry << 1; 17 | } while (carry != 0); 18 | return sum; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /codes/java/67/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | private static final int ZERO = (int) '0'; 4 | private static final int NINE = (int) '9'; 5 | 6 | public int StrToInt(String str) { 7 | int len = str.length(); 8 | if (len == 0) { 9 | return 0; 10 | } 11 | // 最终结果带的符号 12 | int symbol = 1; 13 | int res = 0; 14 | int start = 0; 15 | char[] chars = str.toCharArray(); 16 | 17 | // 如果字符串的第 0 号索引表示的是"符号",那么,数值的转换从索引为 1 处开始 18 | if (chars[0] == '-') { 19 | symbol = -1; 20 | start = 1; 21 | } 22 | if (chars[0] == '+') { 23 | start = 1; 24 | } 25 | for (int i = start; i < len; i++) { 26 | // 字符 '0' 的 ASCII 值是 48 27 | // 字符 '9' 的 ASCII 值是 57 28 | if (chars[i] < ZERO || chars[i] > NINE) { 29 | return 0; 30 | } 31 | res = res * 10 + chars[i] - ZERO; 32 | } 33 | return res * symbol; 34 | } 35 | 36 | public static void main(String[] args) { 37 | System.out.println((int) '0'); 38 | System.out.println((int) '9'); 39 | } 40 | } -------------------------------------------------------------------------------- /codes/java/7/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | public class Solution { 12 | 13 | public TreeNode reConstructBinaryTree(int[] pre, int[] in) { 14 | TreeNode root = reConstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1); 15 | return root; 16 | } 17 | 18 | /** 19 | * 根据前序遍历数组的 [preL, preR] 和 中序遍历数组的 [inL, inR] 重新组建二叉树 20 | * 21 | * @param pre 前序遍历数组 22 | * @param preL 前序遍历数组的区间左端点 23 | * @param preR 前序遍历数组的区间右端点 24 | * @param in 中序遍历数组 25 | * @param inL 中序遍历数组的区间左端点 26 | * @param inR 中序遍历数组的区间右端点 27 | * @return 构建的新二叉树的根结点 28 | */ 29 | private TreeNode reConstructBinaryTree(int[] pre, int preL, int preR, int[] in, int inL, int inR) { 30 | if (preL > preR || inL > inR) { 31 | return null; 32 | } 33 | // 构建的新二叉树的根结点一定是前序遍历数组的第 1 个元素 34 | TreeNode root = new TreeNode(pre[preL]); 35 | // 从中序遍历的左区间端点开始找,找到和前序遍历数组的第 1 个元素的值相等的节点 36 | int i = inL; 37 | while (in[i] != pre[preL] && i <= inR) { 38 | i++; 39 | } 40 | // 在中序遍历数组中遍历了几个元素: i - inL 41 | // 接下来就是递归调用,关键的地方在于找前序遍历数组和中序遍历数组对应的区间的端点 42 | root.left = reConstructBinaryTree(pre, preL + 1, preL + (i - inL), in, inL, i - 1); 43 | root.right = reConstructBinaryTree(pre, preL + (i - inL) + 1, preR, in, i + 1, inR); 44 | return root; 45 | } 46 | } -------------------------------------------------------------------------------- /codes/java/9/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Stack; 2 | 3 | public class Solution { 4 | /** 5 | * 专门 push 的时候用 6 | */ 7 | private Stack stack1 = new Stack(); 8 | /** 9 | * 专门 pop 的时候用 10 | */ 11 | private Stack stack2 = new Stack(); 12 | 13 | private State lastState = State.PUSH; 14 | 15 | enum State { 16 | PUSH, POP 17 | } 18 | 19 | public void push(int node) { 20 | if (lastState == State.PUSH) { 21 | stack1.add(node); 22 | } else { 23 | assert lastState == State.POP; 24 | // 如果上一步是 pop 的话, 25 | while (!stack2.isEmpty()) { 26 | stack1.add(stack2.pop()); 27 | } 28 | stack1.add(node); 29 | lastState = State.PUSH; 30 | } 31 | } 32 | 33 | public int pop() { 34 | if (lastState == State.POP) { 35 | if (stack2.empty()) { 36 | throw new IllegalArgumentException("queue is empty"); 37 | } 38 | return stack2.pop(); 39 | } else { 40 | // 如果上一步是 PUSH 的话 41 | while (!stack1.empty()) { 42 | stack2.add(stack1.pop()); 43 | } 44 | lastState = State.POP; 45 | return stack2.pop(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /codes/java/JumpFloor/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 1 2 3 5 8 4 | // 1 2 3 4 5 5 | public int JumpFloor(int target) { 6 | int n = target; 7 | int[] dp = new int[n + 1]; 8 | dp[0] = 1; 9 | dp[1] = 1; 10 | for (int i = 2; i <= n; i++) { 11 | dp[i] = dp[i - 1] + dp[i - 2]; 12 | } 13 | return dp[n]; 14 | } 15 | 16 | // i j (i+j) 17 | // 1 2 3 5 18 | // 1 2 3 4 19 | public int JumpFloor1(int target) { 20 | if (target == 1) { 21 | return 1; 22 | } 23 | int n = target; 24 | int i = 1; 25 | int j = 2; 26 | int temp; 27 | for (int k = 3; k <= n; k++) { 28 | temp = j; 29 | j = i + j; 30 | i = temp; 31 | } 32 | return j; 33 | } 34 | 35 | public static void main(String[] args) { 36 | Solution solution = new Solution(); 37 | for (int i = 1; i < 5; i++) { 38 | int jumpFloor = solution.JumpFloor1(i); 39 | System.out.println(jumpFloor); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /codes/java/JumpFloorII/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | // 1 2 3 3 | public int JumpFloorII(int target) { 4 | if (target == 0 || target == 1) { 5 | return 1; 6 | } 7 | int n = target; 8 | int[] dp = new int[n + 1]; 9 | dp[1] = 1; 10 | dp[2] = 2; 11 | for (int i = 3; i <= n; i++) { 12 | // 起点是 1 这一点要特别小心 13 | int res = 1; 14 | for (int j = 1; j < i; j++) { 15 | res += dp[j]; 16 | } 17 | dp[i] = res; 18 | } 19 | return dp[n]; 20 | } 21 | 22 | public static void main(String[] args) { 23 | Solution solution = new Solution(); 24 | int jumpFloorII = solution.JumpFloorII(3); 25 | System.out.println(jumpFloorII); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /codes/python/0 到 n-1 中缺失的数字.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def getMissingNumber(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | 8 | size = len(nums) 9 | l = 0 10 | r = size 11 | 12 | while l < r: 13 | 14 | mid = l + (r - l) // 2 15 | if nums[mid] > mid: 16 | # [0,1,2,3,4,6] 17 | # mid 有可能是要求的数 18 | r = mid 19 | else: 20 | assert nums[mid] <= mid 21 | l = mid + 1 22 | return l 23 | 24 | 25 | if __name__ == '__main__': 26 | solution = Solution() 27 | nums = [0, 1, 2, 4] 28 | result = solution.getMissingNumber(nums) 29 | print(result) 30 | -------------------------------------------------------------------------------- /codes/python/10-1、跳台阶.py: -------------------------------------------------------------------------------- 1 | # 10-2、变态跳台阶 2 | 3 | # 使用滚动变量 4 | 5 | 6 | class Solution(object): 7 | def Fibonacci(self, n): 8 | """ 9 | :type n: int 10 | :rtype: int 11 | """ 12 | 13 | if n == 0: 14 | return 0 15 | if n == 1: 16 | return 1 17 | a = 0 18 | b = 1 19 | 20 | while n: 21 | c = a + b 22 | a = b 23 | b = c 24 | n -= 1 25 | return a 26 | -------------------------------------------------------------------------------- /codes/python/10-2、变态跳台阶.py: -------------------------------------------------------------------------------- 1 | # 10-2、变态跳台阶 2 | 3 | # 4 | 5 | 6 | class Solution: 7 | def jumpFloorII(self, number): 8 | if number == 0: 9 | return 1 10 | if number == 1: 11 | return 1 12 | dp = [1 for _ in range(number + 1)] 13 | dp[0] = 0 14 | dp[1] = 1 15 | for i in range(2, number + 1): 16 | for j in range(1, i): 17 | dp[i] += dp[j] 18 | return dp[number] 19 | -------------------------------------------------------------------------------- /codes/python/12-矩阵中的路径.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | directions = [(-1, 0), (1, 0), (0, 1), (0, -1)] 3 | 4 | def hasPath(self, matrix, string): 5 | """ 6 | :type matrix: List[List[str]] 7 | :type string: str 8 | :rtype: bool 9 | """ 10 | rows = len(matrix) 11 | if rows == 0: 12 | return False 13 | cols = len(matrix[0]) 14 | 15 | marked = [[False for _ in range(cols)] for _ in range(rows)] 16 | 17 | for i in range(rows): 18 | for j in range(cols): 19 | if self.__has_path(matrix, string, 0, i, j, marked, rows, cols): 20 | return True 21 | return False 22 | 23 | def __has_path(self, matrix, word, index, start_x, start_y, marked, m, n): 24 | # 注意:首先判断极端情况 25 | if index == len(word) - 1: 26 | return matrix[start_x][start_y] == word[-1] 27 | if matrix[start_x][start_y] == word[index]: 28 | # 先占住这个位置,搜索不成功的话,要释放掉 29 | marked[start_x][start_y] = True 30 | for direction in self.directions: 31 | new_x = start_x + direction[0] 32 | new_y = start_y + direction[1] 33 | if 0 <= new_x < m and 0 <= new_y < n and not marked[new_x][new_y]: 34 | if self.__has_path(matrix, word, index + 1, new_x, new_y, marked, m, n): 35 | return True 36 | marked[start_x][start_y] = False 37 | return False 38 | 39 | 40 | if __name__ == '__main__': 41 | matrix = [ 42 | ["A", "B", "C", "E"], 43 | ["S", "F", "E", "S"], 44 | ["A", "D", "E", "E"] 45 | ] 46 | 47 | str = "ABCEFSADEESE" 48 | 49 | solution = Solution() 50 | result = solution.hasPath(matrix, str) 51 | print(result) 52 | -------------------------------------------------------------------------------- /codes/python/13-机器人的运动范围.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | 3 | def __count_bit_sum(self, num): 4 | res = 0 5 | while num: 6 | res += num % 10 7 | num //= 10 8 | return res 9 | 10 | def __in_area(self, x, y, rows, cols): 11 | return 0 <= x < rows and 0 <= y < cols 12 | 13 | def movingCount(self, threshold, rows, cols): 14 | """ 15 | :type threshold: int 16 | :type rows: int 17 | :type cols: int 18 | :rtype: int 19 | """ 20 | if threshold < 0 or rows == 0 or cols == 0: 21 | return 0 22 | 23 | if threshold == 0: 24 | return 1 25 | 26 | directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] 27 | marked = [[False for _ in range(cols)] for _ in range(rows)] 28 | 29 | queue = [(0, 0)] 30 | res = 0 31 | 32 | while queue: 33 | top_x, top_y = queue.pop(0) 34 | 35 | for direction in directions: 36 | new_x = top_x + direction[0] 37 | new_y = top_y + direction[1] 38 | 39 | if self.__in_area(new_x, new_y, rows, cols) \ 40 | and not marked[new_x][new_y] \ 41 | and self.__count_bit_sum(new_x) + self.__count_bit_sum(new_y) <= threshold: 42 | queue.append((new_x, new_y)) 43 | # 注意:应该写在这里,而不是 pop 出队列的时候 44 | marked[new_x][new_y] = True 45 | res += 1 46 | return res 47 | 48 | 49 | if __name__ == '__main__': 50 | k = 18 51 | m = 40 52 | n = 40 53 | solution = Solution() 54 | result = solution.movingCount(k, m, n) 55 | print(result) 56 | -------------------------------------------------------------------------------- /codes/python/14-剪绳子.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def maxProductAfterCutting(self, length): 3 | """ 4 | :type length: int 5 | :rtype: int 6 | """ 7 | 8 | assert length > 1 9 | 10 | dp = [0 for _ in range(length + 1)] 11 | 12 | dp[1] = 1 13 | 14 | for i in range(2, length + 1): 15 | for j in range(1, i): 16 | dp[i] = max(dp[i], j * (i - j), j * dp[i - j]) 17 | return dp[length] 18 | 19 | 20 | if __name__ == '__main__': 21 | length = 8 22 | 23 | solution = Solution() 24 | result = solution.maxProductAfterCutting(length) 25 | print(result) 26 | -------------------------------------------------------------------------------- /codes/python/15、二进制中 1 的个数-1.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def NumberOf1(self, n): 3 | """ 4 | :type n: int 5 | :rtype: int 6 | """ 7 | # print((-1 & (2**31-1)) >> 1) 8 | # print((-3) >> 1) 9 | n = n & (2 ** 32 - 1) 10 | # print(n) 11 | count = 0 12 | while n != 0: 13 | if n & 1 == 1: 14 | count += 1 15 | n = n >> 1 16 | # print(n) 17 | return count 18 | 19 | 20 | if __name__ == '__main__': 21 | ALL_ONE = 2 ** 32 - 1 22 | a = 0xffffffff 23 | print(ALL_ONE) 24 | print(a) 25 | -------------------------------------------------------------------------------- /codes/python/15、二进制中 1 的个数.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def NumberOf1(self, n): 3 | """ 4 | :type n: int 5 | :rtype: int 6 | """ 7 | ans = 0 8 | for i in range(32): 9 | if n & 1: 10 | ans += 1 11 | n = n >> 1 12 | 13 | return ans 14 | -------------------------------------------------------------------------------- /codes/python/16-README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 关键:将循环变成递归操作,每次折半求值,避免死板做循环,这种感觉像加法变乘法。 4 | 5 | ### 注意细节:底数为 0 的时候,指数为负数是没有意义的 6 | 7 | ### 精确计算,转成浮点数 0.125 8 | System.out.println((double) 1 / 8); 9 | 10 | ### 右移 1 位运算等价于 除以 2 11 | // exponent 指数,exponent >> 1 表示将指数除以 2 12 | System.out.println(exponent >> 1); 13 | 14 | 15 | ### 使用位运算的 与 运算符代替了求余数运算,来判断一个数是奇数还是偶数 16 | if ((exponent & 1) == 0) { -------------------------------------------------------------------------------- /codes/python/16-数值的整数次方-1.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def Power(self, base, exponent): 3 | """ 4 | :type base: float 5 | :type exponent: int 6 | :rtype: float 7 | """ 8 | 9 | if exponent == 0: 10 | return 1 11 | 12 | if exponent < 0: 13 | return 1 / self.Power(base, -exponent) 14 | 15 | # 如果是奇数 16 | if exponent & 1: 17 | return base * self.Power(base, exponent - 1) 18 | return self.Power(base * base, exponent >> 1) -------------------------------------------------------------------------------- /codes/python/16-数值的整数次方.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def Power(self, base, exponent): 3 | """ 4 | :type base: float 5 | :type exponent: int 6 | :rtype: float 7 | """ 8 | 9 | if exponent < 0: 10 | base = 1 / base 11 | # 负数变成正数 12 | exponent = -exponent 13 | 14 | res = 1 15 | while exponent: 16 | if exponent & 1: 17 | res *= base 18 | base *= base 19 | exponent >>= 1 20 | return res 21 | -------------------------------------------------------------------------------- /codes/python/18-删除链表中重复的结点.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.next = None 6 | 7 | 8 | # 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留。 9 | 10 | class Solution(object): 11 | def deleteDuplication(self, head): 12 | """ 13 | :type head: ListNode 14 | :rtype: ListNode 15 | """ 16 | if head is None: 17 | return None 18 | 19 | dummy = ListNode(-1) 20 | dummy.next = head 21 | cur = dummy 22 | 23 | # 一下子要看两个,所以是 24 | while cur.next and cur.next.next: 25 | if cur.next.val == cur.next.next.val: 26 | # 删除的起点至少是 cur.next.next 27 | del_node = cur.next.next 28 | 29 | while del_node.next and del_node.val == del_node.next.val: 30 | del_node = del_node.next 31 | # 来到了一个新的结点,值不同 32 | 33 | cur.next = del_node.next 34 | del_node.next = None 35 | else: 36 | cur = cur.next 37 | 38 | return dummy.next 39 | -------------------------------------------------------------------------------- /codes/python/19、正则表达式匹配.py: -------------------------------------------------------------------------------- 1 | # 9、正则表达式匹配 2 | class Solution(object): 3 | def isMatch(self, s, p): 4 | """ 5 | :type s: str 6 | :type p: str 7 | :rtype: bool 8 | """ 9 | 10 | n = len(s) 11 | m = len(p) 12 | # 初始化成 -1 表示未计算过 13 | f = [[-1 for _ in range(m + 1)] for _ in range(n + 1)] 14 | 15 | return self.dp(0, 0, s, p, f, n, m) 16 | 17 | def dp(self, x, y, s, p, f, n, m): 18 | 19 | if f[x][y] != -1: 20 | return f[x][y] 21 | if y == m: 22 | # 如果模式串用完了,看看字符串是不是也用完了 23 | f[x][y] = (x == n) 24 | return f[x][y] 25 | first_match = x < n and (s[x] == p[y] or p[y] == '.') 26 | 27 | if y + 1 < m and p[y + 1] == '*': 28 | res = self.dp(x, y + 2, s, p, f, n, m) or self.dp(x + 1, y, s, p, f, n, m) 29 | else: 30 | res = first_match and self.dp(x + 1, y + 1, s, p, f, n, m) 31 | 32 | f[x][y] = res 33 | return f[x][y] 34 | 35 | 36 | if __name__ == '__main__': 37 | solution = Solution() 38 | s = 'aaa' 39 | p = 'ab*ac*a' 40 | result = solution.isMatch(s, p) 41 | print(result) 42 | -------------------------------------------------------------------------------- /codes/python/20-表示数值的字符串.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def isNumber(self, s): 3 | """ 4 | :type s: str 5 | :rtype: bool 6 | """ 7 | size = len(s) 8 | 9 | # 1、去掉多余的空格 10 | i = 0 11 | while i < size and s[i] == ' ': 12 | i += 1 13 | 14 | j = size - 1 15 | while j >= 0 and s[j] == ' ': 16 | j -= 1 17 | if i > j: 18 | return False 19 | 20 | s = s[i:j - i + 1] 21 | if s[0] == '+' or s[0] == '-': 22 | s = s[1:] 23 | if len(s) == 0: 24 | return False 25 | if len(s) == 1 and s[0] == '.': 26 | return False 27 | # 点的个数 28 | dot_cnt = 0 29 | # e 的个数 30 | e_cnt = 0 31 | 32 | size = len(s) 33 | i = -1 34 | while i < size - 1: 35 | i += 1 36 | if '0' <= s[i] <= '9': 37 | continue 38 | elif s[i] == '.': 39 | dot_cnt += 1 40 | # 如果没有 e,并且点的数量大于 1 41 | if e_cnt or dot_cnt > 1: 42 | return False 43 | elif s[i] == 'e' or s[i] == 'E': 44 | e_cnt += 1 45 | if i == 0 or i == size - 1 or e_cnt > 1: 46 | return False 47 | # '.' 后面不能加上 48 | if i == 1 and s[0] == '.': 49 | return False 50 | if s[i + 1] == '+' or s[i + 1] == '-': 51 | if i + 2 == size: 52 | return False 53 | i += 1 54 | else: 55 | return False 56 | return True 57 | 58 | 59 | if __name__ == '__main__': 60 | solution = Solution() 61 | s = '123.45e+6' 62 | result = solution.isNumber(s) 63 | print(result) 64 | -------------------------------------------------------------------------------- /codes/python/21-调整数组顺序使奇数位于偶数前面.py: -------------------------------------------------------------------------------- 1 | # import heapq 2 | # 3 | # l = [-62, -41, -30, -28, -16, -22, -13, -19, -15, -17] 4 | # heapq.heapify(l) 5 | # print(l) 6 | 7 | 8 | class Solution(object): 9 | def reOrderArray(self, array): 10 | """ 11 | :type array: List[int] 12 | :rtype: void 13 | """ 14 | # 特判 15 | size = len(array) 16 | if size < 2: 17 | return 18 | 19 | l = 0 20 | r = size - 1 21 | 22 | while True: 23 | while l <= r and array[l] & 1 == 1: 24 | l += 1 25 | while r >= l and array[r] & 1 == 0: 26 | r -= 1 27 | if l > r: 28 | break 29 | 30 | array[l], array[r] = array[r], array[l] 31 | l += 1 32 | r -= 1 33 | return array 34 | 35 | 36 | if __name__ == '__main__': 37 | array = [1, 2, 3, 4, 5] 38 | solution = Solution() 39 | result = solution.reOrderArray(array) 40 | print(result) 41 | -------------------------------------------------------------------------------- /codes/python/22-链表中倒数第k个节点.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution(object): 8 | def findKthToTail(self, pListHead, k): 9 | """ 10 | :type pListHead: ListNode 11 | :type k: int 12 | :rtype: ListNode 13 | """ 14 | if pListHead is None: 15 | return None 16 | counter = 0 17 | p = pListHead 18 | while p: 19 | counter += 1 20 | p = p.next 21 | if k > counter: 22 | return None 23 | p = pListHead 24 | for _ in range(counter - k): 25 | p = p.next 26 | return p 27 | -------------------------------------------------------------------------------- /codes/python/22-链表中倒数第k个节点(快慢指针).py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.next = None 6 | 7 | 8 | class Solution(object): 9 | def findKthToTail(self, pListHead, k): 10 | """ 11 | :type pListHead: ListNode 12 | :type k: int 13 | :rtype: ListNode 14 | """ 15 | if pListHead is None: 16 | return None 17 | fast = pListHead 18 | # 要注意的临界点1: 19 | for _ in range(k - 1): 20 | fast = fast.next 21 | if fast is None: 22 | return None 23 | slow = pListHead 24 | # 要注意的临界点2: 25 | while fast.next: 26 | slow = slow.next 27 | fast = fast.next 28 | return slow 29 | -------------------------------------------------------------------------------- /codes/python/22-链表中倒数第k个节点(练习).py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution(object): 8 | def findKthToTail(self, pListHead, k): 9 | """ 10 | :type pListHead: ListNode 11 | :type k: int 12 | :rtype: ListNode 13 | """ 14 | if pListHead is None: 15 | return None 16 | 17 | fast = pListHead 18 | for _ in range(k - 1): 19 | # 注意:先移动,再判断是否为空 20 | fast = fast.next 21 | if fast is None: 22 | return None 23 | 24 | slow = pListHead 25 | # 注意:下一个结点不为空的时候,才往下走 26 | while fast.next: 27 | slow = slow.next 28 | fast = fast.next 29 | return slow 30 | -------------------------------------------------------------------------------- /codes/python/23-链表中环的入口结点.py: -------------------------------------------------------------------------------- 1 | # 34. 链表中环的入口结点 2 | # 给定一个链表,若其中包含环,则输出环的入口节点。 3 | # 4 | # 若其中不包含环,则输出null。 5 | 6 | # Definition for singly-linked list. 7 | class ListNode(object): 8 | def __init__(self, x): 9 | self.val = x 10 | self.next = None 11 | 12 | 13 | class Solution(object): 14 | def entryNodeOfLoop(self, head): 15 | """ 16 | :type head: ListNode 17 | :rtype: ListNode 18 | """ 19 | # 先考虑边界情况 20 | if head is None or head.next is None: 21 | return None 22 | 23 | slow = head 24 | fast = head 25 | 26 | while fast and fast.next: 27 | # 慢指针走一步,快指针走两步 28 | slow = slow.next 29 | fast = fast.next.next 30 | if slow == fast: 31 | # 说明链表中不存在环 32 | break 33 | 34 | if fast is None or fast.next is None: 35 | return None 36 | 37 | slow = head 38 | while slow != fast: 39 | slow = slow.next 40 | fast = fast.next 41 | # 走到这里,说明 slow == fast 42 | return slow 43 | 44 | 45 | if __name__ == '__main__': 46 | # [1, 2, 3, 7, 4, 5, 6] 47 | l1 = ListNode(1) 48 | l2 = ListNode(2) 49 | l3 = ListNode(3) 50 | l7 = ListNode(7) 51 | l4 = ListNode(4) 52 | l5 = ListNode(5) 53 | l6 = ListNode(6) 54 | l1.next = l2 55 | l2.next = l3 56 | l3.next = l7 57 | l7.next = l4 58 | l4.next = l5 59 | l5.next = l6 60 | l6.next = l2 61 | solution = Solution() 62 | result = solution.entryNodeOfLoop(l1) 63 | print(result) 64 | -------------------------------------------------------------------------------- /codes/python/23-链表中环的入口结点(练习).py: -------------------------------------------------------------------------------- 1 | # 34. 链表中环的入口结点 2 | # 给定一个链表,若其中包含环,则输出环的入口节点。 3 | # 4 | # 若其中不包含环,则输出null。 5 | 6 | # Definition for singly-linked list. 7 | class ListNode(object): 8 | def __init__(self, x): 9 | self.val = x 10 | self.next = None 11 | 12 | 13 | class Solution(object): 14 | def entryNodeOfLoop(self, head): 15 | """ 16 | :type head: ListNode 17 | :rtype: ListNode 18 | """ 19 | if head is None or head.next is None: 20 | return None 21 | 22 | slow = head 23 | fast = head 24 | 25 | while fast and fast.next: 26 | slow = slow.next 27 | fast = fast.next.next 28 | if slow == fast: 29 | break 30 | 31 | if fast is None or fast.next is None: 32 | return None 33 | 34 | slow = head 35 | 36 | while slow != fast: 37 | slow = slow.next 38 | fast = fast.next 39 | return slow 40 | 41 | 42 | if __name__ == '__main__': 43 | # [1, 2, 3, 7, 4, 5, 6] 44 | l1 = ListNode(1) 45 | l2 = ListNode(2) 46 | l3 = ListNode(3) 47 | l7 = ListNode(7) 48 | l4 = ListNode(4) 49 | l5 = ListNode(5) 50 | l6 = ListNode(6) 51 | l1.next = l2 52 | l2.next = l3 53 | l3.next = l7 54 | l7.next = l4 55 | l4.next = l5 56 | l5.next = l6 57 | l6.next = l2 58 | solution = Solution() 59 | result = solution.entryNodeOfLoop(l1) 60 | print(result) 61 | -------------------------------------------------------------------------------- /codes/python/24-反转单链表.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | # 穿针引线,可以看到 while 循环体部分的代码是首尾相连的 8 | # 在 Python 中,其实还有更简便的写法,就跟斐波拉契数列一样 9 | 10 | 11 | class Solution: 12 | def reverseList(self, head): 13 | """ 14 | :type head: ListNode 15 | :rtype: ListNode 16 | """ 17 | 18 | pre = None 19 | cur = head 20 | while cur: 21 | next = cur.next 22 | cur.next = pre 23 | pre = cur 24 | cur = next 25 | return pre 26 | -------------------------------------------------------------------------------- /codes/python/24-反转单链表(Python 语法糖).py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | # 穿针引线,可以看到 while 循环体部分的代码是首尾相连的,有些单链表的题目也有这种规律,感觉很神奇 8 | # 在 Python 中,其实还有更简便的写法,就跟斐波拉契数列一样 9 | 10 | 11 | class Solution: 12 | def reverseList(self, head): 13 | """ 14 | :type head: ListNode 15 | :rtype: ListNode 16 | """ 17 | cur, pre = head, None 18 | while cur: 19 | cur.next, pre, cur = pre, cur, cur.next 20 | return pre 21 | -------------------------------------------------------------------------------- /codes/python/24-反转单链表(递归写法).py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | # 递归写法:用递归就不用思考穿针引线这种事情了。 8 | 9 | 10 | class Solution: 11 | def reverseList(self, head): 12 | """ 13 | :type head: ListNode 14 | :rtype: ListNode 15 | """ 16 | # 递归的终止条件一定要写对:考虑结点为空和但结点的情况 17 | if head is None or head.next is None: 18 | return head 19 | next = head.next 20 | new_head = self.reverseList(next) 21 | next.next = head 22 | head.next = None 23 | return new_head 24 | -------------------------------------------------------------------------------- /codes/python/25、合并排序的链表-穿针引线.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.next = None 6 | 7 | 8 | # 穿针引线的写法,一定要画图才能写出来 9 | # 比较麻烦,还是递归处理简单 10 | 11 | class Solution(object): 12 | def merge(self, l1, l2): 13 | """ 14 | :type l1: ListNode 15 | :type l2: ListNode 16 | :rtype: ListNode 17 | """ 18 | # 引入头结点可以简化对问题的讨论 19 | dummy_node = ListNode(-1) 20 | cur_node = dummy_node 21 | p1 = l1 22 | p2 = l2 23 | 24 | while p1 and p2: 25 | # 两者都不为空,才须要比较 26 | # 其中有一个为空的时候,把其中一个接到另一个尾巴就好了 27 | if p1.val < p2.val: 28 | # next 指针修改 29 | cur_node.next = p1 30 | # p1 后移 31 | p1 = p1.next 32 | else: 33 | cur_node.next = p2 34 | p2 = p2.next 35 | cur_node = cur_node.next 36 | # 跳出循环的时候,一定有:p1 为空或者 p2 为空 37 | # 其中有一个为空的时候,把其中一个接到另一个尾巴就好了 38 | if p1 is None: # 这一句写成 if not p1 也是可以的,不过不好理解 39 | cur_node.next = p2 40 | if not p2: 41 | cur_node.next = p1 42 | return dummy_node.next 43 | -------------------------------------------------------------------------------- /codes/python/25、合并排序的链表.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | 8 | class Solution(object): 9 | def merge(self, l1, l2): 10 | """ 11 | :type l1: ListNode 12 | :type l2: ListNode 13 | :rtype: ListNode 14 | """ 15 | 16 | if l1 is None: 17 | return l2 18 | if l2 is None: 19 | return l1 20 | 21 | # 代码能走到这里说明 l1 和 l2 均非空 22 | # 比较那个小就行了 23 | if l1.val < l2.val: 24 | l1.next = self.merge(l1.next, l2) 25 | return l1 26 | # 走到这里 l1.val >= l2.val 27 | l2.next = self.merge(l1, l2.next) 28 | return l2 29 | -------------------------------------------------------------------------------- /codes/python/26.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class TreeNode: 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | class Solution: 10 | def HasSubtree(self, pRoot1, pRoot2): 11 | # pRoot1 是大树 12 | # pRoot2 是小树 13 | result = False 14 | if pRoot1 and pRoot2: 15 | # 第 1 步:在树 A 中查找与根结点的值一样的结点 16 | # 这里排除了 pRoot2 是空树的情况 17 | if pRoot1.val == pRoot2.val: 18 | # 判断树 1 是不是包含树 2 19 | result = self.__doesTree1HaveTree2(pRoot1, pRoot2) 20 | if not result: 21 | # 如果树 1 不包含树 2 22 | return self.HasSubtree(pRoot1.left, pRoot2) or self.HasSubtree( 23 | pRoot1.right, pRoot2) 24 | return result 25 | 26 | def __doesTree1HaveTree2(self, pRoot1, pRoot2): 27 | if pRoot2 is None: 28 | return True 29 | if pRoot1 is None: 30 | return False 31 | if pRoot1.val != pRoot2.val: 32 | return False 33 | # 走到这里说明 assert pRoot1.val == pRoot2.val 为 True 34 | return self.__doesTree1HaveTree2(pRoot1.left, pRoot2.left) and self.__doesTree1HaveTree2(pRoot1.right, 35 | pRoot2.right) 36 | -------------------------------------------------------------------------------- /codes/python/27.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class TreeNode: 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | class Solution: 10 | # 返回镜像树的根节点 11 | def Mirror(self, root): 12 | if root is None: 13 | return 14 | stack = [] 15 | while root or stack: 16 | while root: 17 | root.left, root.right = root.right, root.left 18 | stack.append(root) 19 | root = root.left 20 | if stack: 21 | root = stack.pop() 22 | root = root.right 23 | -------------------------------------------------------------------------------- /codes/python/27、反转二叉树-后序遍历.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | 9 | class Solution(object): 10 | def mirror(self, root): 11 | """ 12 | :type root: TreeNode 13 | :rtype: void 14 | """ 15 | # 先写递归终止条件 16 | if root is None: 17 | return root 18 | 19 | # 按照后序遍历的方式 20 | self.mirror(root.left) 21 | self.mirror(root.right) 22 | root.left, root.right = root.right, root.left 23 | -------------------------------------------------------------------------------- /codes/python/27、反转二叉树-层序遍历.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | 9 | class Solution(object): 10 | def mirror(self, root): 11 | """ 12 | :type root: TreeNode 13 | :rtype: void 14 | """ 15 | # 先写递归终止条件 16 | if root is None: 17 | return root 18 | queue = [root] 19 | while queue: 20 | top = queue.pop(0) 21 | top.left, top.right = top.right, top.left 22 | if top.left: 23 | queue.append(top.left) 24 | if top.right: 25 | queue.append(top.right) 26 | return root 27 | -------------------------------------------------------------------------------- /codes/python/27、反转二叉树.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | 9 | class Solution(object): 10 | def mirror(self, root): 11 | """ 12 | :type root: TreeNode 13 | :rtype: void 14 | """ 15 | # 先写递归终止条件 16 | if root is None: 17 | return root 18 | 19 | # 按照前序遍历的方式 20 | root.left, root.right = root.right, root.left 21 | self.mirror(root.left) 22 | self.mirror(root.right) 23 | -------------------------------------------------------------------------------- /codes/python/28-对称的二叉树.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | # 递归写法:得引入辅助函数 10 | 11 | class Solution(object): 12 | def isSymmetric(self, root): 13 | """ 14 | :type root: TreeNode 15 | :rtype: bool 16 | """ 17 | # 先写递归终止条件 18 | if root is None: 19 | return True 20 | return self.__helper(root.left, root.right) 21 | 22 | def __helper(self, p1, p2): 23 | if p1 is None and p2 is None: 24 | return True 25 | if p1 is None or p2 is None: 26 | return False 27 | return p1.val == p2.val and self.__helper(p1.left, p2.right) and self.__helper(p1.right, p2.left) 28 | -------------------------------------------------------------------------------- /codes/python/28-对称的二叉树(使用双端队列的写法).py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | # 非递归写法:借助双端队列辅助判断 10 | 11 | class Solution(object): 12 | def isSymmetric(self, root): 13 | """ 14 | :type root: TreeNode 15 | :rtype: bool 16 | """ 17 | # 先写递归终止条件 18 | if root is None: 19 | return True 20 | 21 | # 其实应该用 from collections import deque 22 | deque = [] 23 | 24 | deque.insert(0, root.left) 25 | deque.append(root.right) 26 | 27 | while deque: 28 | l_node = deque.pop(0) 29 | r_node = deque.pop() 30 | 31 | if l_node is None and r_node is None: 32 | continue 33 | if l_node is None or r_node is None: 34 | return False 35 | # 代码走到这里一定有 l_node 和 r_node 非空 36 | # 因此可以取出 val 进行判断了 37 | if l_node.val != r_node.val: 38 | return False 39 | deque.insert(0, l_node.right) 40 | deque.insert(0, l_node.left) 41 | deque.append(r_node.left) 42 | deque.append(r_node.right) 43 | return True 44 | -------------------------------------------------------------------------------- /codes/python/29.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | # matrix类型为二维列表,需要返回列表 4 | def printMatrix(self, matrix): 5 | rows = len(matrix) 6 | cols = len(matrix[0]) 7 | result = [] 8 | if rows == 0 and cols == 0: 9 | return result 10 | left, right, top, buttom = 0, cols - 1, 0, rows - 1 11 | while left <= right and top <= buttom: 12 | for i in range(left, right + 1): 13 | result.append(matrix[top][i]) 14 | for i in range(top + 1, buttom + 1): 15 | result.append(matrix[i][right]) 16 | if top != buttom: 17 | for i in range(left, right)[::-1]: 18 | result.append(matrix[buttom][i]) 19 | if left != right: 20 | for i in range(top + 1, buttom)[::-1]: 21 | result.append(matrix[i][left]) 22 | left += 1 23 | top += 1 24 | right -= 1 25 | buttom -= 1 26 | return result 27 | -------------------------------------------------------------------------------- /codes/python/3-不修改数组找出重复的数字.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def duplicateInArray(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype int 6 | """ 7 | 8 | size = len(nums) 9 | assert size > 1 10 | 11 | l = 1 12 | r = size - 1 13 | 14 | while l < r: 15 | mid = l + (r - l + 1) // 2 16 | counter = 0 17 | for num in nums: 18 | if num < mid: 19 | counter += 1 20 | if counter < mid: 21 | # 小于 4 的数最多只能是 3 个 22 | # 符合的话,重复的数一定在 [mid,right] 中 23 | l = mid 24 | else: 25 | assert counter >= mid 26 | 27 | r = mid - 1 28 | # 不要返回 nums[l] 了,l 和 r 不是索引 29 | return l 30 | -------------------------------------------------------------------------------- /codes/python/3-数组中重复的数字.py: -------------------------------------------------------------------------------- 1 | # 3、数组中重复的数字 2 | 3 | class Solution(object): 4 | def duplicateInArray(self, nums): 5 | """ 6 | :type nums: List[int] 7 | :rtype int 8 | """ 9 | 10 | l = len(nums) 11 | if l == 0: 12 | return -1 13 | 14 | for num in nums: 15 | if num < 0 or num >= l: 16 | return -1 17 | for i in range(l): 18 | while nums[i] != i: 19 | if nums[i] == nums[nums[i]]: 20 | return nums[i] 21 | # 注意:千万不能这么写!!! nums[i], nums[nums[i]] = nums[nums[i]], nums[i] 22 | 23 | nums[nums[i]], nums[i] = nums[i], nums[nums[i]] 24 | # self.__swap(nums, i, nums[i]) 25 | return -1 26 | 27 | def __swap(self, nums, index1, index2): 28 | if index1 == index2: 29 | return 30 | temp = nums[index1] 31 | nums[index1] = nums[index2] 32 | nums[index2] = temp 33 | 34 | 35 | if __name__ == '__main__': 36 | nums = [2, 3, 5, 4, 3, 2, 6, 7] 37 | solution = Solution() 38 | result = solution.duplicateInArray(nums) 39 | print(result) 40 | -------------------------------------------------------------------------------- /codes/python/3-桶排序.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def duplicateInArray(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype int 6 | """ 7 | 8 | size = len(nums) 9 | if size < 2: 10 | return -1 11 | 12 | for i in range(size): 13 | if nums[i] < 0 or nums[i] > size - 1: 14 | return -1 15 | 16 | for i in range(size): 17 | 18 | # nums[i] 应该在 i 的位置上 19 | 20 | while i != nums[i]: 21 | if nums[i] == nums[nums[i]]: 22 | return nums[i] 23 | self.__swap(nums, i, nums[i]) 24 | return -1 25 | 26 | def __swap(self, nums, index1, index2): 27 | if index1 == index2: 28 | return 29 | temp = nums[index1] 30 | nums[index1] = nums[index2] 31 | nums[index2] = temp 32 | -------------------------------------------------------------------------------- /codes/python/30-包含 min 的栈.py: -------------------------------------------------------------------------------- 1 | # 定义两个栈,一个存放入的值,另一个存最小值,两个栈应该是同步 push 和 pop,否则还要分类讨论,代码编写容易出错。 2 | 3 | 4 | class MinStack(object): 5 | 6 | def __init__(self): 7 | """ 8 | initialize your data structure here. 9 | """ 10 | self.stack = [] 11 | self.helper = [] 12 | 13 | def push(self, x): 14 | """ 15 | :type x: int 16 | :rtype: void 17 | """ 18 | 19 | if len(self.stack) == 0: 20 | self.helper.append(x) 21 | self.stack.append(x) 22 | else: 23 | # 如果将要 push 的元素比辅助栈的栈顶元素还大,不能放这个元素, 24 | # 此时应该把辅助栈的栈顶元素再复制一份 25 | peek = self.helper[-1] 26 | if x > peek: 27 | self.stack.append(x) 28 | self.helper.append(peek) 29 | else: 30 | self.stack.append(x) 31 | self.helper.append(x) 32 | 33 | def pop(self): 34 | """ 35 | :rtype: void 36 | """ 37 | 38 | if len(self.stack) == 0: 39 | return 40 | self.helper.pop() 41 | return self.stack.pop() 42 | 43 | def top(self): 44 | """ 45 | :rtype: int 46 | """ 47 | return self.stack[-1] 48 | 49 | def getMin(self): 50 | """ 51 | :rtype: int 52 | """ 53 | return self.helper[-1] 54 | 55 | # Your MinStack object will be instantiated and called as such: 56 | # obj = MinStack() 57 | # obj.push(x) 58 | # obj.pop() 59 | # param_3 = obj.top() 60 | # param_4 = obj.getMin() 61 | -------------------------------------------------------------------------------- /codes/python/30-包含 min 的栈(大雪菜的做法).py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liweiwei1419/sword-for-offer-solution/4c57462cbaa365b07341bb6ed20d21a4f0389f33/codes/python/30-包含 min 的栈(大雪菜的做法).py -------------------------------------------------------------------------------- /codes/python/31-栈的压入、弹出序列.py: -------------------------------------------------------------------------------- 1 | # 42. 栈的压入、弹出序列 2 | # 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。 3 | # 4 | # 假设压入栈的所有数字均不相等。 5 | # 6 | # 例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。 7 | # 8 | # 注意:若两个序列为空或长度不等则视为并不是一个栈的压入、弹出序列。 9 | 10 | 11 | class Solution(object): 12 | def isPopOrder(self, pushV, popV): 13 | """ 14 | :type pushV: list[int] 15 | :type popV: list[int] 16 | :rtype: bool 17 | """ 18 | if len(pushV) == 0 and len(popV) == 0: 19 | return False 20 | if pushV is None or popV is None or len(pushV) != len(popV): 21 | return False 22 | stack = [] 23 | index = 0 24 | for ele in pushV: 25 | stack.append(ele) 26 | while stack and stack[-1] == popV[index]: 27 | stack.pop() 28 | index += 1 29 | return len(stack) == 0 30 | 31 | 32 | if __name__ == '__main__': 33 | pushV = [] 34 | popV = [] 35 | solution = Solution() 36 | result = solution.isPopOrder(pushV, popV) 37 | print(result) 38 | -------------------------------------------------------------------------------- /codes/python/31.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def IsPopOrder(self, pushV, popV): 4 | if pushV is None or popV is None: 5 | return False 6 | stack = [] 7 | index = 0 8 | for num in pushV: 9 | stack.append(num) 10 | while stack and stack[-1] == popV[index]: 11 | stack.pop() 12 | index += 1 13 | return len(stack) == 0 14 | -------------------------------------------------------------------------------- /codes/python/32-不分行从上往下打印二叉树.py: -------------------------------------------------------------------------------- 1 | # 43. 不分行从上往下打印二叉树 2 | # 从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。 3 | # 4 | 5 | # Definition for a binary tree node. 6 | class TreeNode(object): 7 | def __init__(self, x): 8 | self.val = x 9 | self.left = None 10 | self.right = None 11 | 12 | 13 | class Solution: 14 | def printFromTopToBottom(self, root): 15 | """ 16 | :type root: TreeNode 17 | :rtype: List[int] 18 | """ 19 | if root is None: 20 | return [] 21 | queue = [root] 22 | res = [] 23 | while queue: 24 | # 弹出队首元素,索引编号 0 不要忘记写了 25 | top = queue.pop(0) 26 | res.append(top.val) 27 | if top.left: 28 | queue.append(top.left) 29 | if top.right: 30 | queue.append(top.right) 31 | return res 32 | -------------------------------------------------------------------------------- /codes/python/32-之字形打印二叉树.py: -------------------------------------------------------------------------------- 1 | # 45. 之字形打印二叉树 2 | # 请实现一个函数按照之字形顺序从上向下打印二叉树。 3 | # 4 | # 即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。 5 | # 6 | # 样例 7 | # 输入如下图所示二叉树[8, 12, 2, null, null, 6, 4, null, null, null, null] 8 | # 8 9 | # / \ 10 | # 12 2 11 | # / \ 12 | # 6 4 13 | # 输出:[[8], [2, 12], [6, 4]] 14 | 15 | # Definition for a binary tree node. 16 | 17 | 18 | class TreeNode(object): 19 | def __init__(self, x): 20 | self.val = x 21 | self.left = None 22 | self.right = None 23 | 24 | 25 | class Solution(object): 26 | def printFromTopToBottom(self, root): 27 | """ 28 | :type root: TreeNode 29 | :rtype: List[List[int]] 30 | """ 31 | if root is None: 32 | return [] 33 | queue = [root] 34 | res = [] 35 | turn_left = True 36 | while queue: 37 | cur_list = [] 38 | size = len(queue) 39 | for _ in range(size): 40 | top = queue.pop(0) 41 | if turn_left: 42 | cur_list.append(top.val) 43 | else: 44 | cur_list.insert(0, top.val) 45 | if top.left: 46 | queue.append(top.left) 47 | if top.right: 48 | queue.append(top.right) 49 | res.append(cur_list) 50 | turn_left = not turn_left 51 | return res 52 | 53 | 54 | if __name__ == '__main__': 55 | res = [] 56 | res.insert(0, 1) 57 | res.insert(0, 2) 58 | res.insert(0, 3) 59 | print(res) 60 | 61 | a = True 62 | for _ in range(10): 63 | a = not a 64 | print(a) 65 | -------------------------------------------------------------------------------- /codes/python/32-分行从上往下打印二叉树.py: -------------------------------------------------------------------------------- 1 | # 44. 分行从上往下打印二叉树 2 | # 从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。 3 | 4 | # Definition for a binary tree node. 5 | class TreeNode(object): 6 | def __init__(self, x): 7 | self.val = x 8 | self.left = None 9 | self.right = None 10 | 11 | 12 | class Solution(object): 13 | def printFromTopToBottom(self, root): 14 | """ 15 | :type root: TreeNode 16 | :rtype: List[List[int]] 17 | """ 18 | if root is None: 19 | return [] 20 | queue = [root] 21 | res = [] 22 | while queue: 23 | size = len(queue) 24 | cur_list = [] 25 | for _ in range(size): 26 | top = queue.pop(0) 27 | cur_list.append(top.val) 28 | if top.left: 29 | queue.append(top.left) 30 | if top.right: 31 | queue.append(top.right) 32 | res.append(cur_list) 33 | return res 34 | -------------------------------------------------------------------------------- /codes/python/33-二叉搜索树的后序遍历序列.py: -------------------------------------------------------------------------------- 1 | # 33. 二叉搜索树的后序遍历序列 2 | 3 | # 4 | # 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。 5 | # 6 | # 如果是则返回true,否则返回false。 7 | # 8 | # 假设输入的数组的任意两个数字都互不相同。 9 | # 10 | # 样例 11 | # 输入:[4, 8, 6, 12, 16, 14, 10] 12 | # 13 | # 输出:true 14 | 15 | 16 | class Solution: 17 | def verifySquenceOfBST(self, sequence): 18 | """ 19 | :type sequence: List[int] 20 | :rtype: bool 21 | """ 22 | # 先写特殊情况 23 | l = len(sequence) 24 | if l == 0: 25 | return False 26 | if l == 1: 27 | return True 28 | 29 | return self.__helper(sequence, 0, l - 1) 30 | 31 | def __helper(self, sequence, left, right): 32 | # 先写递归终止条件 33 | if left >= right: 34 | return True 35 | # 此时区间最右边的数作为标定元素 36 | pivot = sequence[right] 37 | # 设置一个遍历指针,把 [left, right -1] 这个区间里的元素全部看一遍 38 | 39 | # 正确的情况是:最右边的元素把前面的数组分成两部分: 40 | # 第 1 部分的元素全部严格小于最右边的元素 41 | # 第 2 部分的元素全部严格大于最右边的元素 42 | point = left 43 | while sequence[point] < pivot: 44 | point += 1 45 | # 此时 [left, point - 1] 中的元素都严格比最右边的元素小 46 | # 下面就依次验证后面的元素是不是都严格比最右边的元素大就好了 47 | mid = point - 1 48 | # 此后,所有的数都应该比 pivot 大 49 | while point < right: 50 | if sequence[point] > pivot: 51 | point += 1 52 | else: 53 | return False 54 | return self.__helper(sequence, left, mid) and self.__helper( 55 | sequence, mid + 1, right - 1) 56 | 57 | 58 | if __name__ == '__main__': 59 | # sequence = [4, 8, 6, 12, 16, 14, 10] 60 | sequence = [2, 1, 3] 61 | solution = Solution() 62 | result = solution.verifySquenceOfBST(sequence) 63 | print(result) 64 | -------------------------------------------------------------------------------- /codes/python/34-二叉树中和为某一值的路径.py: -------------------------------------------------------------------------------- 1 | # 47. 二叉树中和为某一值的路径 2 | # 3 | # 输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 4 | # 5 | # 从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 6 | # 7 | # 样例 8 | # 给出二叉树如下所示,并给出num=22。 9 | # 5 10 | # / \ 11 | # 4 6 12 | # / / \ 13 | # 12 13 6 14 | # / \ / \ 15 | # 9 1 5 1 16 | # 17 | # 输出:[[5,4,12,1],[5,6,6,5]] 18 | 19 | # Definition for a binary tree node. 20 | class TreeNode(object): 21 | def __init__(self, x): 22 | self.val = x 23 | self.left = None 24 | self.right = None 25 | 26 | 27 | class Solution(object): 28 | def findPath(self, root, sum): 29 | """ 30 | :type root: TreeNode 31 | :type sum: int 32 | :rtype: List[List[int]] 33 | """ 34 | res = [] 35 | if root is None: 36 | return res 37 | self.__dfs(root, sum, [], res) 38 | return res 39 | 40 | def __dfs(self, node, residue, path, res): 41 | # 递归,就应该先写递归终止条件 42 | if node is None: 43 | return 44 | # 走到这里 node 肯定非空,所以可以使用 left 和 right 成员变量 45 | # 走完以后,要记得回溯,状态要重置 46 | # 先把它加到路径中,在各种 if 都不成立的最后,要记得 pop 出去 47 | path.append(node.val) 48 | if node.left is None and node.right is None: 49 | # 如果是叶子结点,并且 residue 就等于当前结点的值 50 | if node.val == residue: 51 | res.append(path[:]) 52 | # 注意:这里不要 return ,如果要 return,return 之前把 path 执行 pop 操作 53 | # 走到这里是非叶子结点,所以左边要走一走,右边也要走一走 54 | if node.left: 55 | self.__dfs(node.left, residue - node.val, path, res) 56 | if node.right: 57 | self.__dfs(node.right, residue - node.val, path, res) 58 | path.pop() -------------------------------------------------------------------------------- /codes/python/34-二叉树中和为某一值的路径(解法2).py: -------------------------------------------------------------------------------- 1 | # 47. 二叉树中和为某一值的路径 2 | # 3 | # 输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 4 | # 5 | # 从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 6 | # 7 | # 样例 8 | # 给出二叉树如下所示,并给出num=22。 9 | # 5 10 | # / \ 11 | # 4 6 12 | # / / \ 13 | # 12 13 6 14 | # / \ / \ 15 | # 9 1 5 1 16 | # 17 | # 输出:[[5,4,12,1],[5,6,6,5]] 18 | 19 | # Definition for a binary tree node. 20 | class TreeNode(object): 21 | def __init__(self, x): 22 | self.val = x 23 | self.left = None 24 | self.right = None 25 | 26 | 27 | class Solution(object): 28 | def findPath(self, root, sum): 29 | """ 30 | :type root: TreeNode 31 | :type sum: int 32 | :rtype: List[List[int]] 33 | """ 34 | res = [] 35 | if root is None: 36 | return res 37 | self.__dfs(root, sum, [], res) 38 | return res 39 | 40 | def __dfs(self, node, residue, path, res): 41 | if node is None: 42 | return 43 | path.append(node.val) 44 | residue -= node.val 45 | 46 | if node.left is None and node.right is None and residue == 0: 47 | # 才用结算 48 | res.append(path[:]) 49 | path.pop() 50 | return 51 | 52 | if node.left: 53 | self.__dfs(node.left, residue, path, res) 54 | 55 | if node.right: 56 | self.__dfs(node.right, residue, path, res) 57 | path.pop() -------------------------------------------------------------------------------- /codes/python/35-复杂链表的复刻.py: -------------------------------------------------------------------------------- 1 | # 48. 复杂链表的复刻 2 | # 3 | # 4 | # 请实现一个函数可以复制一个复杂链表。 5 | # 6 | # 在复杂链表中,每个结点除了有一个指针指向下一个结点外,还有一个额外的指针指向链表中的任意结点或者null。 7 | 8 | # Definition for singly-linked list with a random pointer. 9 | class ListNode(object): 10 | def __init__(self, x): 11 | self.val = x 12 | self.next = None 13 | self.random = None 14 | 15 | 16 | class Solution(object): 17 | def copyRandomList(self, head): 18 | """ 19 | :type head: ListNode 20 | :rtype: ListNode 21 | """ 22 | if head is None: 23 | return None 24 | map = dict() 25 | dummy_node = ListNode(-1) 26 | # p 指针用于新链表的 next 指针赋值 27 | p = dummy_node 28 | 29 | # 遍历一次链表,做两件事 30 | # 1、复制结点 31 | # 2、只管 next 指针 32 | cur_node = head 33 | while cur_node: 34 | new_node = ListNode(cur_node.val) 35 | # 把新旧结点的对应关系放在一个 map 里 36 | map[cur_node] = new_node 37 | cur_node = cur_node.next 38 | 39 | p.next = new_node 40 | p = new_node 41 | 42 | # 接下来做随机指针的复制 43 | for old_node, new_node in map.items(): 44 | # 要记得判断是否为空,否则 None 不能作为 map key 45 | if old_node.random: 46 | new_node.random = map[old_node.random] 47 | return dummy_node.next 48 | -------------------------------------------------------------------------------- /codes/python/35-复杂链表的复刻(书上介绍的方法).py: -------------------------------------------------------------------------------- 1 | # 48. 复杂链表的复刻 2 | # 3 | # 4 | # 请实现一个函数可以复制一个复杂链表。 5 | # 6 | # 在复杂链表中,每个结点除了有一个指针指向下一个结点外,还有一个额外的指针指向链表中的任意结点或者null。 7 | 8 | # Definition for singly-linked list with a random pointer. 9 | class ListNode(object): 10 | def __init__(self, x): 11 | self.val = x 12 | self.next = None 13 | self.random = None 14 | 15 | 16 | class Solution(object): 17 | def copyRandomList(self, head): 18 | """ 19 | :type head: ListNode 20 | :rtype: ListNode 21 | """ 22 | if head is None: 23 | return None 24 | 25 | # 第 1 步:根据 next 指针复制出一个新旧合一的链表 26 | cur_node = head 27 | while cur_node: 28 | # 先暂存 cur_node 的 next_node 下一次遍历要用 29 | next_node = cur_node.next 30 | new_node = ListNode(cur_node.val) 31 | 32 | cur_node.next = new_node 33 | new_node.next = next_node 34 | # 指针遍历到下一个结点 35 | cur_node = next_node 36 | # 第 2 步:根据旧结点 random 指针,给新结点的 random 指针做出正确的指向 37 | cur_node = head 38 | while cur_node: 39 | new_node = cur_node.next 40 | # 同样要先暂存 cur_node.next_node 41 | next_node = new_node.next 42 | # 要记得做非空判断,因为题目中说了 random 有可能为空 43 | new_node.random = cur_node.random.next if cur_node.random else None 44 | cur_node = next_node 45 | 46 | # 第 3 步:旧结点和新结点分离(拆分链表) 47 | cur_node = head 48 | res = cur_node.next 49 | while cur_node: 50 | new_node = cur_node.next 51 | next_node = new_node.next 52 | # 恢复原始结点 53 | cur_node.next = new_node.next 54 | # 恢复拷贝结点 55 | # 这里也要同样注意空指针的问题,克隆结点的最后一个结点的下一个结点是 null 56 | new_node.next = next_node.next if next_node else None 57 | cur_node = next_node 58 | return res 59 | -------------------------------------------------------------------------------- /codes/python/36-二叉搜索树与双向链表.py: -------------------------------------------------------------------------------- 1 | # 36. 二叉搜索树与双向链表 2 | # 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 3 | # 要求不能创建任何新的结点,只能调整树中结点指针的指向。 4 | 5 | # Definition for a binary tree node. 6 | class TreeNode(object): 7 | def __init__(self, x): 8 | self.val = x 9 | self.left = None 10 | self.right = None 11 | 12 | 13 | class Solution(object): 14 | 15 | def __init__(self): 16 | self.linked_list_tail = None 17 | self.res = None 18 | 19 | def convert(self, root): 20 | """ 21 | :type root: TreeNode 22 | :rtype: TreeNode 23 | """ 24 | self.__dfs(root) 25 | return self.res 26 | 27 | # 中序遍历 28 | def __dfs(self, root): 29 | if root is None: 30 | return 31 | self.__dfs(root.left) 32 | 33 | if self.linked_list_tail is None: 34 | self.linked_list_tail = root 35 | self.res = root 36 | else: 37 | self.linked_list_tail.right = root 38 | root.left = self.linked_list_tail 39 | self.linked_list_tail = root 40 | self.__dfs(root.right) 41 | -------------------------------------------------------------------------------- /codes/python/36-二叉搜索树与双向链表(返回 tuple 的写法).py: -------------------------------------------------------------------------------- 1 | # 36. 二叉搜索树与双向链表 2 | # 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 3 | # 要求不能创建任何新的结点,只能调整树中结点指针的指向。 4 | 5 | # Definition for a binary tree node. 6 | class TreeNode(object): 7 | def __init__(self, x): 8 | self.val = x 9 | self.left = None 10 | self.right = None 11 | 12 | 13 | class Solution(object): 14 | 15 | def convert(self, root): 16 | """ 17 | :type root: TreeNode 18 | :rtype: TreeNode 19 | """ 20 | if root is None: 21 | return None 22 | head, _ = self.__dfs(root) 23 | 24 | return head 25 | 26 | def __dfs(self, root): 27 | # 如果这个结点是叶子结点 28 | if root.left is None and root.right is None: 29 | return (root, root) 30 | 31 | # 如果有左孩子,还有右边孩子 32 | if root.left and root.right: 33 | ll, lr = self.__dfs(root.left) 34 | rl, rr = self.__dfs(root.right) 35 | # 下面穿针引线 36 | lr.right = root 37 | root.left = lr 38 | root.right = rl 39 | rl.left = root 40 | return (ll, rr) 41 | # 走到这里,就是二者之一为空 42 | if root.left: 43 | ll, lr = self.__dfs(root.left) 44 | lr.right = root 45 | root.left = lr 46 | return (ll, root) 47 | 48 | if root.right: 49 | rl, rr = self.__dfs(root.right) 50 | root.right = rl 51 | rl.left = root 52 | return (root, rr) 53 | -------------------------------------------------------------------------------- /codes/python/37-序列化、反序列化二叉树.py: -------------------------------------------------------------------------------- 1 | # 37、序列化、反序列化二叉树 2 | 3 | 4 | # Definition for a binary tree node. 5 | class TreeNode(object): 6 | def __init__(self, x): 7 | self.val = x 8 | self.left = None 9 | self.right = None 10 | 11 | 12 | class Solution: 13 | 14 | # 前序遍历 15 | def serialize(self, root): 16 | """Encodes a tree to a single string. 17 | 18 | :type root: TreeNode 19 | :rtype: str 20 | """ 21 | 22 | res = '' 23 | if root is None: 24 | # 后面这个空格不能丢 25 | return '! ' 26 | res += str(root.val) 27 | res += ' ' 28 | res += self.serialize(root.left) 29 | res += self.serialize(root.right) 30 | return res 31 | 32 | def deserialize(self, data): 33 | """Decodes your encoded data to tree. 34 | 35 | :type data: str 36 | :rtype: TreeNode 37 | """ 38 | arr = data.split(' ') 39 | return self.__helper(arr) 40 | 41 | def __helper(self, arr): 42 | if arr: 43 | top = arr.pop(0) 44 | if top != '!': 45 | root = TreeNode(int(top)) 46 | root.left = self.__helper(arr) 47 | root.right = self.__helper(arr) 48 | return root 49 | else: 50 | return None 51 | 52 | 53 | if __name__ == '__main__': 54 | solution = Solution() 55 | 56 | n8 = TreeNode(8) 57 | n12 = TreeNode(12) 58 | n2 = TreeNode(2) 59 | n6 = TreeNode(6) 60 | n4 = TreeNode(4) 61 | 62 | n8.left = n12 63 | n8.right = n2 64 | n2.left = n6 65 | n2.right = n4 66 | 67 | result = solution.serialize(n8) 68 | print(result) 69 | 70 | result1 = solution.deserialize(result) 71 | print(result1.val) 72 | -------------------------------------------------------------------------------- /codes/python/37-序列化、反序列化二叉树(解法2).py: -------------------------------------------------------------------------------- 1 | # 37、序列化、反序列化二叉树 2 | 3 | 4 | # Definition for a binary tree node. 5 | class TreeNode(object): 6 | def __init__(self, x): 7 | self.val = x 8 | self.left = None 9 | self.right = None 10 | 11 | 12 | class Solution: 13 | 14 | # 前序遍历 15 | def serialize(self, root): 16 | """Encodes a tree to a single string. 17 | 18 | :type root: TreeNode 19 | :rtype: str 20 | """ 21 | 22 | res = [] 23 | if root is None: 24 | return '!' 25 | 26 | stack = [root] 27 | while stack: 28 | top = stack.pop() 29 | if top is None: 30 | res.append('!') 31 | else: 32 | stack.append(top.right) 33 | stack.append(top.left) 34 | res.append(str(top.val)) 35 | return ' '.join(res) 36 | 37 | def deserialize(self, data): 38 | """Decodes your encoded data to tree. 39 | 40 | :type data: str 41 | :rtype: TreeNode 42 | """ 43 | queue = data.split(' ') 44 | return self.__build_tree(queue) 45 | 46 | def __build_tree(self, queue): 47 | if queue: 48 | top = queue.pop(0) 49 | if top != '!': 50 | root = TreeNode(int(top)) 51 | root.left = self.__build_tree(queue) 52 | root.right = self.__build_tree(queue) 53 | return root 54 | else: 55 | return None 56 | # 如果 queue 为空,就什么都不做 57 | 58 | 59 | if __name__ == '__main__': 60 | solution = Solution() 61 | 62 | n8 = TreeNode(8) 63 | n12 = TreeNode(12) 64 | n2 = TreeNode(2) 65 | n6 = TreeNode(6) 66 | n4 = TreeNode(4) 67 | 68 | n8.left = n12 69 | n8.right = n2 70 | n2.left = n6 71 | n2.right = n4 72 | 73 | result = solution.serialize(n8) 74 | print(result) 75 | 76 | result1 = solution.deserialize(result) 77 | print(result1.val) 78 | -------------------------------------------------------------------------------- /codes/python/38-字符串的排列(重要,回溯,如何去掉重复元素)-大雪菜的做法.py: -------------------------------------------------------------------------------- 1 | # 38、数字排列 2 | # 输入一组数字(可能包含重复数字),输出其所有的排列方式。 3 | # 4 | # 样例 5 | # 输入:[1,2,3] 6 | # 7 | # 输出: 8 | # [ 9 | # [1,2,3], 10 | # [1,3,2], 11 | # [2,1,3], 12 | # [2,3,1], 13 | # [3,1,2], 14 | # [3,2,1] 15 | # ] 16 | 17 | # 参考资料:https://www.acwing.com/solution/AcWing/content/776/ 18 | 19 | class Solution: 20 | def permutation(self, nums): 21 | """ 22 | :type nums: List[int] 23 | :rtype: List[List[int]] 24 | """ 25 | 26 | l = len(nums) 27 | res = [] 28 | if l == 0: 29 | return res 30 | # 因为含有重复数组,所以先排序 31 | nums.sort() 32 | marked = [False for _ in range(l)] 33 | path = [0 for _ in range(l)] 34 | self.__dfs(nums, 0, 0, path, marked, res) 35 | return res 36 | 37 | def __dfs(self, nums, index, start, path, marked, res): 38 | if index == len(nums): 39 | res.append(path[:]) 40 | return 41 | for i in range(start, len(nums)): 42 | if not marked[i]: 43 | marked[i] = True 44 | path[i] = nums[index] 45 | if index + 1 < len(nums) and nums[index] != nums[index + 1]: 46 | self.__dfs(nums, index + 1, 0, path, marked, res) 47 | else: 48 | self.__dfs(nums, index + 1, i + 1, path, marked, res) 49 | marked[i] = False 50 | 51 | 52 | if __name__ == '__main__': 53 | nums = [1, 1, 2] 54 | solution = Solution() 55 | result = solution.permutation(nums) 56 | print(result) 57 | -------------------------------------------------------------------------------- /codes/python/38-字符串的排列(重要,回溯,如何去掉重复元素)-大雪菜的做法2.py: -------------------------------------------------------------------------------- 1 | # 38、数字排列 2 | # 输入一组数字(可能包含重复数字),输出其所有的排列方式。 3 | # 4 | # 样例 5 | # 输入:[1,2,3] 6 | # 7 | # 输出: 8 | # [ 9 | # [1,2,3], 10 | # [1,3,2], 11 | # [2,1,3], 12 | # [2,3,1], 13 | # [3,1,2], 14 | # [3,2,1] 15 | # ] 16 | 17 | # 参考资料:https://www.acwing.com/solution/AcWing/content/776/ 18 | 19 | class Solution: 20 | def permutation(self, nums): 21 | """ 22 | :type nums: List[int] 23 | :rtype: List[List[int]] 24 | """ 25 | 26 | l = len(nums) 27 | res = [] 28 | if l == 0: 29 | return res 30 | # 因为含有重复数组,所以先排序 31 | nums.sort() 32 | path = [0 for _ in range(l)] 33 | self.__dfs(nums, 0, 0, path, 0, res) 34 | 35 | return res 36 | 37 | def __dfs(self, nums, index, start, path, state, res): 38 | if index == len(nums): 39 | res.append(path[:]) 40 | return 41 | 42 | if index == 0 or nums[index] != nums[index - 1]: 43 | start = 0 44 | 45 | for i in range(start, len(nums)): 46 | if (state >> i & 1) == 0: 47 | # 如果当前的数没有使用过 48 | path[i] = nums[index] 49 | self.__dfs(nums, index + 1, i + 1, path, state + (1 << i), res) 50 | 51 | 52 | if __name__ == '__main__': 53 | nums = [1, 1, 2] 54 | solution = Solution() 55 | result = solution.permutation(nums) 56 | print(result) 57 | -------------------------------------------------------------------------------- /codes/python/38-字符串的排列(重要,回溯,如何去掉重复元素).py: -------------------------------------------------------------------------------- 1 | # 38、数字排列 2 | # 输入一组数字(可能包含重复数字),输出其所有的排列方式。 3 | # 4 | # 样例 5 | # 输入:[1,2,3] 6 | # 7 | # 输出: 8 | # [ 9 | # [1,2,3], 10 | # [1,3,2], 11 | # [2,1,3], 12 | # [2,3,1], 13 | # [3,1,2], 14 | # [3,2,1] 15 | # ] 16 | 17 | 18 | class Solution: 19 | def permutation(self, nums): 20 | """ 21 | :type nums: List[int] 22 | :rtype: List[List[int]] 23 | """ 24 | 25 | l = len(nums) 26 | res = [] 27 | if l == 0: 28 | return res 29 | # 因为含有重复数组,所以先排序 30 | nums.sort() 31 | marked = [False for _ in range(l)] 32 | self.__dfs(nums, 0, [], marked, res) 33 | return res 34 | 35 | def __dfs(self, nums, start, path, marked, res): 36 | if start == len(nums): 37 | res.append(path[:]) 38 | return 39 | for i in range(len(nums)): 40 | if not marked[i]: 41 | if i > 0 and nums[i] == nums[i - 1] and not marked[i - 1]: 42 | continue 43 | marked[i] = True 44 | path.append(nums[i]) 45 | self.__dfs(nums, start + 1, path, marked, res) 46 | path.pop() 47 | marked[i] = False 48 | 49 | 50 | if __name__ == '__main__': 51 | nums = [1, 1, 2] 52 | solution = Solution() 53 | result = solution.permutation(nums) 54 | print(result) 55 | -------------------------------------------------------------------------------- /codes/python/39-数组中出现次数超过一半的数字.py: -------------------------------------------------------------------------------- 1 | # 39、数组中出现次数超过一半的数字 2 | # 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 3 | # 4 | # 假设数组非空,并且一定存在满足条件的数字。 5 | # 6 | # 思考题: 7 | # 8 | # 假设要求只能使用 O(n) 的时间和额外 O(1) 的空间,该怎么做呢? 9 | # 样例 10 | # 输入:[1,2,1,1,3] 11 | # 12 | # 输出:1 13 | class Solution(object): 14 | def moreThanHalfNum_Solution(self, nums): 15 | """ 16 | :type nums: List[int] 17 | :rtype: int 18 | """ 19 | 20 | l = len(nums) 21 | if l == 1: 22 | return nums[0] 23 | 24 | num = nums[0] 25 | times = 1 26 | for i in range(1, l): 27 | # 注意分类讨论的顺序,先看次数是不是 0 28 | # 以下的 3 种情况是互斥的 29 | if times == 0: 30 | num = nums[i] 31 | times += 1 32 | elif num == nums[i]: 33 | times += 1 34 | else: 35 | times -= 1 36 | return num 37 | -------------------------------------------------------------------------------- /codes/python/39-数组中出现次数超过一半的数字(牛客网).py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def MoreThanHalfNum_Solution(self, numbers): 4 | res = numbers[0] 5 | times = 1 6 | for num in numbers[1:]: 7 | if times == 0: 8 | res = num 9 | times = 1 10 | elif res == num: 11 | times += 1 12 | else: 13 | times -= 1 14 | # 验证 res 是不是超过一半 15 | times = 0 16 | for num in numbers: 17 | if num == res: 18 | times += 1 19 | return res if times > len(numbers) // 2 else 0 20 | -------------------------------------------------------------------------------- /codes/python/4-二维数组中的查找.py: -------------------------------------------------------------------------------- 1 | # 4、二维数组中的查找 2 | 3 | class Solution(object): 4 | 5 | # 二分法查找规律 6 | # 1、从右到左,找第 1 个小于或者等于 target 的数 7 | # 2、从上到下,找第 1 个大于或者等于 target 的数 8 | 9 | def searchArray(self, array, target): 10 | """ 11 | :type array: List[List[int]] 12 | :type target: int 13 | :rtype: bool 14 | """ 15 | 16 | rows = len(array) 17 | if rows == 0: 18 | return False 19 | cols = len(array[0]) 20 | 21 | col = cols - 1 22 | row = 0 23 | 24 | while row < rows and col >= 0: 25 | 26 | # print('row', row, 'col', col, array[row][0]) 27 | # 1、从右到左,找第 1 个小于或者等于 target 的数 28 | if col == 0 and array[row][0] > target: 29 | return False 30 | l = 0 31 | r = col 32 | while l < r: 33 | mid = l + (r - l + 1) // 2 34 | if array[row][mid] <= target: 35 | l = mid 36 | else: 37 | assert array[row][mid] > target 38 | r = mid - 1 39 | col = l 40 | 41 | # 2、从上到下,找第 1 个大于或者等于 target 的数 42 | if row == rows - 1 and array[rows - 1][col] < target: 43 | return False 44 | 45 | l = row 46 | r = rows - 1 47 | while l < r: 48 | mid = l + (r - l) // 2 49 | if array[mid][col] >= target: 50 | r = mid 51 | else: 52 | assert array[mid][col] < target 53 | l = mid + 1 54 | row = l 55 | 56 | if array[row][col] == target: 57 | return True 58 | 59 | return False 60 | 61 | 62 | if __name__ == '__main__': 63 | array = [[1, 2, 8, 9], 64 | [2, 4, 9, 12], 65 | [4, 7, 10, 13], 66 | [6, 8, 11, 15]] 67 | target = 16 68 | solution = Solution() 69 | result = solution.searchArray(array, target) 70 | print(result) 71 | 72 | -------------------------------------------------------------------------------- /codes/python/4-二维数组中的查找(非二分).py: -------------------------------------------------------------------------------- 1 | # 4、二维数组中的查找 2 | 3 | class Solution(object): 4 | 5 | def searchArray(self, array, target): 6 | rows = len(array) 7 | if rows == 0: 8 | return False 9 | 10 | cols = len(array[0]) 11 | if rows > 0 and cols > 0: 12 | row = 0 13 | col = cols - 1 14 | while row < rows and col >= 0: 15 | if target == array[row][col]: 16 | return True 17 | elif target < array[row][col]: 18 | col -= 1 19 | else: 20 | row += 1 21 | return False 22 | 23 | 24 | if __name__ == '__main__': 25 | array = [[1, 2, 8, 9], 26 | [2, 4, 9, 12], 27 | [4, 7, 10, 13], 28 | [6, 8, 11, 15]] 29 | target = 16 30 | solution = Solution() 31 | result = solution.searchArray(array, target) 32 | print(result) 33 | -------------------------------------------------------------------------------- /codes/python/40-最小的 K 个数(partition).py: -------------------------------------------------------------------------------- 1 | # 40、最小的 K 个数(partition) 2 | # 输入n个整数,找出其中最小的k个数。 3 | # 4 | # 注意: 5 | # 6 | # 数据保证k一定小于等于输入数组的长度; 7 | # 输出数组内元素请按从小到大顺序排序; 8 | # 样例 9 | # 输入:[1,2,3,4,5,6,7,8] , k=4 10 | # 11 | # 输出:[1,2,3,4] 12 | 13 | 14 | class Solution(object): 15 | def getLeastNumbers_Solution(self, input, k): 16 | """ 17 | :type input: list[int] 18 | :type k: int 19 | :rtype: list[int] 20 | """ 21 | 22 | size = len(input) 23 | 24 | if size == 0: 25 | return [] 26 | if k == size: 27 | return sorted(input) 28 | l = 0 29 | r = size - 1 30 | while l <= r: 31 | p = self.__partition(input, l, r) 32 | if p == k - 1: 33 | return sorted(input[:p + 1]) 34 | elif p > k - 1: 35 | # 此时 k-1 p 36 | r = p - 1 37 | else: 38 | # 此时 p k-1 39 | l = p + 1 40 | 41 | def __partition(self, input, left, right): 42 | # 只有一个数的时候,就没有必要 partition 了 43 | # 直接返回这个数的索引 44 | if left == right: 45 | return left 46 | pivot = input[left] 47 | 48 | j = left 49 | # [left+1,j] 这个区间里的元素都严格小于 pivot 50 | for i in range(left + 1, right + 1): 51 | if input[i] < pivot: 52 | j += 1 53 | input[i], input[j] = input[j], input[i] 54 | input[left], input[j] = input[j], input[left] 55 | return j 56 | 57 | 58 | if __name__ == '__main__': 59 | input = [9, 14, 1, 16, 19, 13, 12] 60 | k = 4 61 | solution = Solution() 62 | result = solution.getLeastNumbers_Solution(input, k) 63 | print(result) 64 | -------------------------------------------------------------------------------- /codes/python/40-最小的 K 个数(二路-partition).py: -------------------------------------------------------------------------------- 1 | # 40、最小的 K 个数(partition) 2 | # 输入n个整数,找出其中最小的k个数。 3 | # 4 | # 注意: 5 | # 6 | # 数据保证k一定小于等于输入数组的长度; 7 | # 输出数组内元素请按从小到大顺序排序; 8 | # 样例 9 | # 输入:[1,2,3,4,5,6,7,8] , k=4 10 | # 11 | # 输出:[1,2,3,4] 12 | 13 | 14 | class Solution(object): 15 | def getLeastNumbers_Solution(self, input, k): 16 | """ 17 | :type input: list[int] 18 | :type k: int 19 | :rtype: list[int] 20 | """ 21 | 22 | size = len(input) 23 | 24 | if size == 0: 25 | return [] 26 | if k == size: 27 | return sorted(input) 28 | l = 0 29 | r = size - 1 30 | while l <= r: 31 | p = self.__partition(input, l, r) 32 | if p == k - 1: 33 | return sorted(input[:p + 1]) 34 | elif p > k - 1: 35 | # 此时 k-1 p 36 | r = p - 1 37 | else: 38 | # 此时 p k-1 39 | l = p + 1 40 | 41 | def __partition(self, input, left, right): 42 | # 只有一个数的时候,就没有必要 partition 了 43 | # 直接返回这个数的索引 44 | if left == right: 45 | return left 46 | pivot = input[left] 47 | l = left + 1 48 | r = right 49 | while True: 50 | while l <= right and input[l] <= pivot: 51 | l += 1 52 | while r > left and input[r] >= pivot: 53 | r -= 1 54 | if l > r: 55 | break 56 | input[l], input[r] = input[r], input[l] 57 | l += 1 58 | r -= 1 59 | input[left], input[r] = input[r], input[left] 60 | return r 61 | 62 | 63 | if __name__ == '__main__': 64 | input = [9, 14, 1, 16, 19, 13, 12] 65 | k = 4 66 | solution = Solution() 67 | result = solution.getLeastNumbers_Solution(input, k) 68 | print(result) 69 | -------------------------------------------------------------------------------- /codes/python/40-最小的 K 个数(小顶堆).py: -------------------------------------------------------------------------------- 1 | # 40、最小的 K 个数(小顶堆) 2 | # 输入n个整数,找出其中最小的k个数。 3 | # 4 | # 注意: 5 | # 6 | # 数据保证k一定小于等于输入数组的长度; 7 | # 输出数组内元素请按从小到大顺序排序; 8 | # 样例 9 | # 输入:[1,2,3,4,5,6,7,8] , k=4 10 | # 11 | # 输出:[1,2,3,4] 12 | 13 | 14 | class Solution(object): 15 | 16 | def getLeastNumbers_Solution(self, input, k): 17 | """ 18 | :type input: list[int] 19 | :type k: int 20 | :rtype: list[int] 21 | """ 22 | size = len(input) 23 | if size == 0: 24 | return [] 25 | if k == size: 26 | return sorted(input) 27 | import heapq 28 | 29 | l = [] 30 | for num in input[:k]: 31 | heapq.heappush(l, -num) 32 | for num in input[k:]: 33 | top = l[0] 34 | if top < -num: 35 | heapq.heappushpop(l, -num) 36 | return sorted([-num for num in l]) 37 | 38 | def getLeastNumbers_Solution1(self, input, k): 39 | """ 40 | :type input: list[int] 41 | :type k: int 42 | :rtype: list[int] 43 | """ 44 | size = len(input) 45 | if size == 0: 46 | return [] 47 | if k == size: 48 | return sorted(input) 49 | import heapq 50 | heapq.heapify(input) 51 | return sorted(heapq.nsmallest(k, input)) 52 | 53 | 54 | if __name__ == '__main__': 55 | input = [9, 14, 1, 16, 19, 13, 12] 56 | k = 4 57 | solution = Solution() 58 | result = solution.getLeastNumbers_Solution(input, k) 59 | print(result) 60 | -------------------------------------------------------------------------------- /codes/python/41-数据流中的中位数.py: -------------------------------------------------------------------------------- 1 | # 54. 数据流中的中位数 2 | # 3 | # 4 | # 如何得到一个数据流中的中位数? 5 | # 6 | # 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。 7 | # 8 | # 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。 9 | # 10 | # 样例 11 | # 输入:1, 2, 3, 4 12 | # 13 | # 输出:1,1.5,2,2.5 14 | # 15 | # 解释:每当数据流读入一个数据,就进行一次判断并输出当前的中位数。 16 | 17 | import heapq 18 | 19 | 20 | class Solution: 21 | 22 | def __init__(self): 23 | self.min_heap = [] 24 | self.max_heap = [] 25 | self.count = 0 26 | 27 | def insert(self, num): 28 | """ 29 | :type num: int 30 | :rtype: void 31 | """ 32 | self.count += 1 33 | if self.count & 1 == 1: 34 | heapq.heappush(self.max_heap, -num) 35 | temp = -heapq.heappop(self.max_heap) 36 | heapq.heappush(self.min_heap, temp) 37 | else: 38 | heapq.heappush(self.min_heap, num) 39 | temp = heapq.heappop(self.min_heap) 40 | heapq.heappush(self.max_heap, -temp) 41 | 42 | # print(self.min_heap) 43 | # print(self.max_heap) 44 | 45 | def getMedian(self): 46 | """ 47 | :rtype: float 48 | """ 49 | if self.count & 1 == 1: 50 | return self.min_heap[0] 51 | else: 52 | return (self.min_heap[0] + (-self.max_heap[0])) / 2 53 | 54 | 55 | if __name__ == '__main__': 56 | solution = Solution() 57 | solution.insert(1) 58 | result = solution.getMedian() 59 | print(result) 60 | solution.insert(2) 61 | result = solution.getMedian() 62 | print(result) 63 | 64 | solution.insert(3) 65 | result = solution.getMedian() 66 | print(result) 67 | 68 | solution.insert(4) 69 | result = solution.getMedian() 70 | print(result) 71 | -------------------------------------------------------------------------------- /codes/python/41-数据流中的中位数(更清晰的写法).py: -------------------------------------------------------------------------------- 1 | # 54. 数据流中的中位数 2 | # 3 | # 4 | # 如何得到一个数据流中的中位数? 5 | # 6 | # 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。 7 | # 8 | # 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。 9 | # 10 | # 样例 11 | # 输入:1, 2, 3, 4 12 | # 13 | # 输出:1,1.5,2,2.5 14 | # 15 | # 解释:每当数据流读入一个数据,就进行一次判断并输出当前的中位数。 16 | 17 | import heapq 18 | 19 | 20 | class Solution: 21 | 22 | def __init__(self): 23 | self.min_heap = [] 24 | self.max_heap = [] 25 | self.count = 0 26 | 27 | def insert(self, num): 28 | """ 29 | :type num: int 30 | :rtype: void 31 | """ 32 | # 当前是奇数的时候,直接"最小堆" -> "最大堆",就可以了 33 | # 此时"最小堆" 与 "最大堆" 的元素数组是相等的 34 | 35 | # 当前是偶数的时候,"最小堆" -> "最大堆"以后,最终我们要让"最小堆"多一个元素 36 | # 所以应该让 "最大堆" 拿出一个元素给 "最小堆" 37 | 38 | heapq.heappush(self.min_heap, num) 39 | temp = heapq.heappop(self.min_heap) 40 | heapq.heappush(self.max_heap, -temp) 41 | if self.count & 1 == 0: 42 | temp = -heapq.heappop(self.max_heap) 43 | heapq.heappush(self.min_heap, temp) 44 | self.count += 1 45 | # print(self.min_heap) 46 | # print(self.max_heap) 47 | 48 | def getMedian(self): 49 | """ 50 | :rtype: float 51 | """ 52 | if self.count & 1 == 1: 53 | return self.min_heap[0] 54 | else: 55 | return (self.min_heap[0] + (-self.max_heap[0])) / 2 56 | 57 | 58 | if __name__ == '__main__': 59 | solution = Solution() 60 | solution.insert(1) 61 | result = solution.getMedian() 62 | print(result) 63 | solution.insert(2) 64 | result = solution.getMedian() 65 | print(result) 66 | 67 | solution.insert(3) 68 | result = solution.getMedian() 69 | print(result) 70 | 71 | solution.insert(4) 72 | result = solution.getMedian() 73 | print(result) 74 | -------------------------------------------------------------------------------- /codes/python/42-连续子数组的最大和.py: -------------------------------------------------------------------------------- 1 | # 42. 连续子数组的最大和 2 | 3 | 4 | # 输入一个 非空 整型数组,数组里的数可能为正,也可能为负。 5 | # 6 | # 数组中一个或连续的多个整数组成一个子数组。 7 | # 8 | # 求所有子数组的和的最大值。 9 | # 10 | # 要求时间复杂度为O(n)。 11 | # 12 | # 样例 13 | # 输入:[1, -2, 3, 10, -4, 7, 2, -5] 14 | # 15 | # 输出:18 16 | 17 | 18 | class Solution(object): 19 | def maxSubArray(self, nums): 20 | """ 21 | :type nums: List[int] 22 | :rtype: int 23 | """ 24 | 25 | l = len(nums) 26 | if l == 0: 27 | return 0 28 | if l == 1: 29 | return nums[0] 30 | dp = [0 for _ in range(l)] 31 | dp[0] = nums[0] 32 | 33 | for i in range(1, l): 34 | dp[i] = max(dp[i - 1] + nums[i], nums[i]) 35 | # 最后不要忘记拉通求一遍最大值,或者在上面遍历的时候,就保存最大值 36 | return max(dp) 37 | 38 | 39 | if __name__ == '__main__': 40 | nums = [1, -2, 3, 10, -4, 7, 2, -5] 41 | 42 | solution = Solution() 43 | result = solution.maxSubArray(nums) 44 | print(result) 45 | -------------------------------------------------------------------------------- /codes/python/43-整数中 1 出现的次数(从 1 到 n 整数中 1 出现的次数).py: -------------------------------------------------------------------------------- 1 | # 56. 从1到n整数中1出现的次数 2 | # 3 | # 输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。 4 | # 5 | # 例如输入12,从1到12这些整数中包含“1”的数字有1,10,11和12,其中“1”一共出现了5次。 6 | # 7 | # 样例 8 | # 输入: 12 9 | # 输出: 5 10 | class Solution(object): 11 | def numberOf1Between1AndN_Solution(self, n): 12 | """ 13 | :type n: int 14 | :rtype: int 15 | """ 16 | if n <= 0: 17 | return 0 18 | 19 | number = [] 20 | while n: 21 | number.append(n % 10) 22 | n //= 10 23 | 24 | res = 0 25 | for i in range(len(number) - 1, -1, -1): 26 | left = 0 27 | right = 0 28 | # 想清楚这里 t 为什么从 1 开始 29 | t = 1 30 | for j in range(len(number) - 1, i, -1): 31 | left = left * 10 + number[j] 32 | 33 | for j in range(i - 1, -1, -1): 34 | right = right * 10 + number[j] 35 | t *= 10 36 | # print(left, right) 37 | # 至少有左边的数这么多 38 | res += left * t 39 | # print(number[i], left, right, t, left * t) 40 | if number[i] == 1: 41 | res += right + 1 42 | elif number[i] > 1: 43 | res += t 44 | return res 45 | 46 | 47 | if __name__ == '__main__': 48 | solution = Solution() 49 | n = 45032 50 | result = solution.numberOf1Between1AndN_Solution(n) 51 | print('result', result) 52 | -------------------------------------------------------------------------------- /codes/python/44-数字序列中某一位的数字.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def digitAtIndex(self, n): 3 | """ 4 | :type n: int 5 | :rtype: int 6 | """ 7 | 8 | # 如果 n 小于 10 ,直接返回就可以了 9 | if n < 10: 10 | return n 11 | 12 | # 计算前缀部分 13 | 14 | base = 9 15 | digits = 1 16 | # 2 位数,从 10 到 99 一共 ( 99 - 10 + 1) * 2 = 90 * 2 = 180 位 17 | # 3 位数,从 100 到 999 一共 ( 999 - 100 + 1) * 2 = 900 * 3 = 2700 位 18 | # 4 位数,从 1000 到 9999 一共 ( 9999 - 1000 + 1) * 2 = 9000 * 4 = 3600 位 19 | 20 | while n - base * digits > 0: 21 | n -= base * digits 22 | base *= 10 23 | digits += 1 24 | 25 | index = n % digits 26 | if index == 0: 27 | # 计算出 num 是多少 28 | # 例如:192,有 1 个位移的偏差 29 | num = 10 ** (digits - 1) + n // digits - 1 30 | # 返回个位就可以了 31 | return num % 10 32 | else: 33 | # 不能整除,那个偏移就不用算了 34 | # 例如 194 = 189 + 5 35 | # 100 + 2 = 102 36 | num = 10 ** (digits - 1) + n // digits 37 | # 从左边向右边数,第 2 位 38 | for i in range(index, digits): 39 | num //= 10 40 | return num % 10 41 | -------------------------------------------------------------------------------- /codes/python/45-把数组排成最小的数.py: -------------------------------------------------------------------------------- 1 | # 45、把数组排成最小的数 2 | # 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 3 | # 4 | # 例如输入数组[3, 32, 321],则打印出这3个数字能排成的最小数字321323。 5 | 6 | 7 | class Solution(object): 8 | def printMinNumber(self, nums): 9 | """ 10 | :type nums: List[int] 11 | :rtype: str 12 | """ 13 | 14 | if len(nums) == 0: 15 | return '' 16 | # 自定义排序规则 17 | from functools import cmp_to_key 18 | key_func = cmp_to_key(lambda a, b: int(a + b) - int(b + a)) 19 | result = sorted(map(str, nums), key=key_func) 20 | return ''.join(result) 21 | 22 | 23 | if __name__ == '__main__': 24 | list1 = [7, -8, 5, 4, 0, -2, -5] 25 | # 要求:1、正数在前负数在后 26 | # 2、正数从小到大 27 | # 3、负数从大到小 28 | 29 | result = sorted(list1, key=lambda x: (x < 0, abs(x))) 30 | print(result) 31 | 32 | s = 'asdf234GDSdsf23' # 排序:小写-大写-奇数-偶数 33 | 34 | print( 35 | "".join( 36 | sorted( 37 | s, 38 | key=lambda x: ( 39 | x.isdigit(), 40 | x.isdigit() and int(x) % 41 | 2 == 0, 42 | x.isupper(), 43 | x)))) 44 | -------------------------------------------------------------------------------- /codes/python/45-把数组排成最小的数(覆盖魔法函数).py: -------------------------------------------------------------------------------- 1 | # 45、把数组排成最小的数 2 | # 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 3 | # 4 | # 例如输入数组[3, 32, 321],则打印出这3个数字能排成的最小数字321323。 5 | 6 | 7 | class NumCompare(str): 8 | def __lt__(self, other): 9 | return int(self + other) - int(other + self) 10 | 11 | 12 | class Solution(object): 13 | def printMinNumber(self, nums): 14 | """ 15 | :type nums: List[int] 16 | :rtype: str 17 | """ 18 | 19 | if len(nums) == 0: 20 | return '' 21 | # 自定义排序规则 22 | result = sorted(map(str, nums), key=NumCompare) 23 | return ''.join(result) 24 | 25 | 26 | if __name__ == '__main__': 27 | nums = [3, 32, 321] 28 | solution = Solution() 29 | result = solution.printMinNumber(nums) 30 | print(result) 31 | -------------------------------------------------------------------------------- /codes/python/46-把数字翻译成字符串.py: -------------------------------------------------------------------------------- 1 | # 46、把数字翻译成字符串 2 | 3 | # 给定一个数字,我们按照如下规则把它翻译为字符串: 4 | # 5 | # 0翻译成”a”,1翻译成”b”,……,11翻译成”l”,……,25翻译成”z”。 6 | # 7 | # 一个数字可能有多个翻译。例如12258有5种不同的翻译,它们分别是”bccfi”、”bwfi”、”bczi”、”mcfi”和”mzi”。 8 | # 9 | # 请编程实现一个函数用来计算一个数字有多少种不同的翻译方法。 10 | # 11 | # 样例 12 | 13 | 14 | class Solution: 15 | def getTranslationCount(self, s): 16 | """ 17 | :type s: str 18 | :rtype: int 19 | """ 20 | s = str(s) 21 | l = len(s) 22 | if l == 0: 23 | return 0 24 | dp = [None for _ in range(l)] 25 | 26 | # dp[i] 表示 s[0,i] ,包括 i ,一共有多少种翻译的方法 27 | 28 | dp[0] = 1 29 | for i in range(1, l): 30 | # 当前值至少是 dp[i-1],因为 s[i] 可以单独翻译 31 | cur = dp[i - 1] 32 | 33 | # 看一看 s[i-1,i] 是不是可以翻译 34 | if 9 < int(s[i - 1:i + 1]) < 26: 35 | if i - 2 < 0: 36 | # 12 37 | cur += 1 38 | else: 39 | # 要考虑到数组下标越界问题 40 | cur += dp[i - 2] 41 | dp[i] = cur 42 | return dp[l - 1] 43 | 44 | 45 | if __name__ == '__main__': 46 | s = 12258 47 | solution = Solution() 48 | result = solution.getTranslationCount(s) 49 | print(result) 50 | -------------------------------------------------------------------------------- /codes/python/47-礼物的最大价值.py: -------------------------------------------------------------------------------- 1 | # 47、礼物的最大价值 2 | 3 | # 在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。 4 | # 5 | # 你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格直到到达棋盘的右下角。 6 | # 7 | # 给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物? 8 | 9 | 10 | class Solution(object): 11 | def getMaxValue(self, grid): 12 | """ 13 | :type grid: List[List[int]] 14 | :rtype: int 15 | """ 16 | 17 | m = len(grid) 18 | if m == 0: 19 | return 0 20 | n = len(grid[0]) 21 | 22 | dp = [None for _ in range(n)] 23 | 24 | dp[0] = grid[0][0] 25 | for i in range(1, n): 26 | dp[i] = dp[i - 1] + grid[0][i] 27 | 28 | for i in range(1, m): 29 | for j in range(n): 30 | if j == 0: 31 | dp[j] += grid[i][0] 32 | else: 33 | dp[j] = grid[i][j] + max(dp[j - 1], dp[j]) 34 | 35 | return dp[n - 1] 36 | 37 | 38 | if __name__ == '__main__': 39 | grid = [ 40 | [2, 3, 1], 41 | [1, 7, 1], 42 | [4, 6, 1] 43 | ] 44 | 45 | solution = Solution() 46 | result = solution.getMaxValue(grid) 47 | print(result) 48 | -------------------------------------------------------------------------------- /codes/python/49-丑数.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | 3 | # 把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。 4 | # 例如 6、8 都是丑数,但 14 不是,因为它包含因子 7 。 5 | # 习惯上我们把 1 当做是第一个丑数。 6 | # 求按从小到大的顺序的第 N 个丑数。 7 | 8 | # 动态规划 9 | 10 | def getUglyNumber(self, n): 11 | """ 12 | :type n: int 13 | :rtype: int 14 | """ 15 | 16 | if n <= 0: 17 | return 0 18 | if n == 1: 19 | return 1 20 | 21 | dp = [None for _ in range(n)] 22 | # 根据题意:习惯上我们把 1 当做第一个丑数。 23 | dp[0] = 1 24 | m2 = 0 25 | m3 = 0 26 | m5 = 0 27 | for i in range(1, n): 28 | dp[i] = min(dp[m2] * 2, dp[m3] * 3, dp[m5] * 5) 29 | while dp[m2] * 2 <= dp[i]: 30 | m2 += 1 31 | while dp[m3] * 3 <= dp[i]: 32 | m3 += 1 33 | while dp[m5] * 5 <= dp[i]: 34 | m5 += 1 35 | return dp[n - 1] 36 | -------------------------------------------------------------------------------- /codes/python/50-字符串中第一个只出现一次的字符.py: -------------------------------------------------------------------------------- 1 | # 50、字符串中第一个只出现一次的字符 2 | # 在字符串中找出第一个只出现一次的字符。 3 | # 4 | # 如输入"abaccdeff",则输出b。 5 | # 6 | # 如果字符串中不存在只出现一次的字符,返回#字符。 7 | # 8 | # 样例: 9 | # 输入:"abaccdeff" 10 | # 11 | # 输出:'b' 12 | 13 | class Solution: 14 | def firstNotRepeatingChar(self, s): 15 | """ 16 | :type s: str 17 | :rtype: str 18 | """ 19 | if len(s) < 1: 20 | return '#' 21 | 22 | counter = [0 for _ in range(256)] 23 | for alpha in s: 24 | counter[ord(alpha)] += 1 25 | for alpha in s: 26 | if counter[ord(alpha)] == 1: 27 | return alpha 28 | # 要注意:如果是 "aabbcc" 这种所有的字符都出现不止 1 次, 29 | # 就按照题意,返回 '#' 30 | return '#' 31 | 32 | 33 | if __name__ == '__main__': 34 | s = "abaccdeff" 35 | solution = Solution() 36 | result = solution.firstNotRepeatingChar(s) 37 | print(result) 38 | -------------------------------------------------------------------------------- /codes/python/50_2-字符流中第一个不重复的字符.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | 3 | def __init__(self): 4 | self.chars = [0 for _ in range(256)] 5 | self.strs = [] 6 | 7 | def firstAppearingOnce(self): 8 | """ 9 | :rtype: str 10 | """ 11 | for char in self.strs: 12 | if self.chars[ord(char)] == 1: 13 | return char 14 | return '#' 15 | 16 | def insert(self, char): 17 | """ 18 | :type char: str 19 | :rtype: void 20 | """ 21 | self.chars[ord(char)] += 1 22 | self.strs.append(char) 23 | -------------------------------------------------------------------------------- /codes/python/51-数组中的逆序对(树状数组解法).py: -------------------------------------------------------------------------------- 1 | # 51、数组中的逆序对(分治解法) 2 | # 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。 3 | # 4 | # 输入一个数组,求出这个数组中的逆序对的总数。 5 | # 6 | # 样例 7 | # 输入:[1,2,3,4,5,6,0] 8 | # 9 | # 输出:6 10 | 11 | 12 | class Solution(object): 13 | def inversePairs(self, nums): 14 | """ 15 | :type nums: List[int] 16 | :rtype: int 17 | """ 18 | 19 | class FenwickTree: 20 | def __init__(self, n): 21 | self.size = n 22 | self.tree = [0 for _ in range(n + 1)] 23 | 24 | def __lowbit(self, index): 25 | return index & (-index) 26 | 27 | # 单点更新:从下到上,最多到 len,可以取等 28 | def update(self, index, delta): 29 | while index <= self.size: 30 | self.tree[index] += delta 31 | index += self.__lowbit(index) 32 | 33 | # 区间查询:从上到下,最少到 1,可以取等 34 | def query(self, index): 35 | res = 0 36 | while index > 0: 37 | res += self.tree[index] 38 | index -= self.__lowbit(index) 39 | return res 40 | 41 | # 特判 42 | l = len(nums) 43 | if l < 2: 44 | return 0 45 | 46 | # 原始数组去除重复以后从小到大排序 47 | s = list(set(nums)) 48 | 49 | # 构建最小堆,因为从小到大一个一个拿出来,用堆比较合适 50 | import heapq 51 | heapq.heapify(s) 52 | 53 | # 由数字查排名 54 | rank_map = dict() 55 | index = 1 56 | # 不重复数字的个数 57 | size = len(s) 58 | for _ in range(size): 59 | num = heapq.heappop(s) 60 | rank_map[num] = index 61 | index += 1 62 | 63 | res = 0 64 | # 树状数组只要不重复数字个数这么多空间就够了 65 | ft = FenwickTree(size) 66 | # 从后向前看,拿出一个数字来,就更新一下,然后向前查询比它小的个数 67 | for i in range(l - 1, -1, -1): 68 | rank = rank_map[nums[i]] 69 | ft.update(rank, 1) 70 | res += ft.query(rank - 1) 71 | return res 72 | 73 | 74 | if __name__ == '__main__': 75 | nums = [1, 2, 3, 4, 5, 6, 0] 76 | solution = Solution() 77 | result = solution.inversePairs(nums) 78 | print(result) 79 | -------------------------------------------------------------------------------- /codes/python/52-两个链表的第一个公共结点.py: -------------------------------------------------------------------------------- 1 | # 66. 两个链表的第一个公共结点 2 | # 输入两个链表,找出它们的第一个公共结点。 3 | # 4 | # 样例 5 | # 给出两个链表如下所示: 6 | # A: a1 → a2 7 | # ↘ 8 | # c1 → c2 → c3 9 | # ↗ 10 | # B: b1 → b2 → b3 11 | # 12 | # 输出第一个公共节点c1 13 | 14 | # Definition for singly-linked list. 15 | class ListNode(object): 16 | def __init__(self, x): 17 | self.val = x 18 | self.next = None 19 | 20 | 21 | class Solution(object): 22 | 23 | def __get_list_node_size(self, root): 24 | node = root 25 | size = 0 26 | while node: 27 | size += 1 28 | node = node.next 29 | return size 30 | 31 | def findFirstCommonNode(self, headA, headB): 32 | """ 33 | :type headA, headB: ListNode 34 | :rtype: ListNode 35 | """ 36 | if headA is None or headB is None: 37 | return None 38 | 39 | s1 = self.__get_list_node_size(headA) 40 | s2 = self.__get_list_node_size(headB) 41 | 42 | # 我们默认 l1 >= l2 43 | h1 = headA 44 | h2 = headB 45 | 46 | if s2 > s1: 47 | # 如果 B 长度更长,把二者交换 48 | h1 = headB 49 | h2 = headA 50 | # 现在 h1 上走 (s1 - s2) 这么多长度 51 | for _ in range(abs(s1 - s2)): 52 | h1 = h1.next 53 | # 然后齐头并进 54 | while h1 and h2 and h1.val != h2.val: 55 | h1 = h1.next 56 | h2 = h2.next 57 | 58 | # 走到这里,如果是因为 h1 和 h2 都空了,返回 Node 59 | if h1 is None and h2 is None: 60 | return None 61 | else: 62 | return h1 63 | -------------------------------------------------------------------------------- /codes/python/52-两个链表的第一个公共结点(用两个栈).py: -------------------------------------------------------------------------------- 1 | # 66. 两个链表的第一个公共结点 2 | # 输入两个链表,找出它们的第一个公共结点。 3 | # 4 | # 样例 5 | # 给出两个链表如下所示: 6 | # A: a1 → a2 7 | # ↘ 8 | # c1 → c2 → c3 9 | # ↗ 10 | # B: b1 → b2 → b3 11 | # 12 | # 输出第一个公共节点c1 13 | 14 | # Definition for singly-linked list. 15 | class ListNode(object): 16 | def __init__(self, x): 17 | self.val = x 18 | self.next = None 19 | 20 | 21 | class Solution(object): 22 | 23 | def findFirstCommonNode(self, headA, headB): 24 | """ 25 | :type headA, headB: ListNode 26 | :rtype: ListNode 27 | """ 28 | if headA is None or headB is None: 29 | return None 30 | stack1 = [] 31 | stack2 = [] 32 | node1 = headA 33 | while node1: 34 | stack1.append(node1) 35 | node1 = node1.next 36 | node2 = headB 37 | while node2: 38 | stack2.append(node2) 39 | node2 = node2.next 40 | # 注意:这里有陷阱,一定要先设置一个 result 结点 41 | # 如果两个链表没有公共元素,res 不会被赋值 42 | res = None 43 | while stack1 and stack2: 44 | node1 = stack1.pop() 45 | node2 = stack2.pop() 46 | if node1.val == node2.val: 47 | # 这里暂存一下,最后一个相等的结点才是我们求的 48 | res = node1 49 | continue 50 | if stack1 is None or stack2 is None: 51 | return None 52 | return res 53 | -------------------------------------------------------------------------------- /codes/python/53-两个链表的第一个公共结点(最佳).py: -------------------------------------------------------------------------------- 1 | # 66. 两个链表的第一个公共结点 2 | # 输入两个链表,找出它们的第一个公共结点。 3 | # 4 | # 样例 5 | # 给出两个链表如下所示: 6 | # A: a1 → a2 7 | # ↘ 8 | # c1 → c2 → c3 9 | # ↗ 10 | # B: b1 → b2 → b3 11 | # 12 | # 输出第一个公共节点c1 13 | 14 | # Definition for singly-linked list. 15 | class ListNode(object): 16 | def __init__(self, x): 17 | self.val = x 18 | self.next = None 19 | 20 | 21 | class Solution(object): 22 | 23 | def findFirstCommonNode(self, headA, headB): 24 | """ 25 | :type headA, headB: ListNode 26 | :rtype: ListNode 27 | """ 28 | if headA is None or headB is None: 29 | return None 30 | p1 = headA 31 | p2 = headB 32 | 33 | while p1 != p2: 34 | if p1 is None: 35 | p1 = headB 36 | else: 37 | p1 = p1.next 38 | if p2 is None: 39 | p2 = headA 40 | else: 41 | p2 = p2.next 42 | 43 | return p1 44 | -------------------------------------------------------------------------------- /codes/python/54-二叉搜索树的第 k 大结点.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | class Solution(object): 10 | def kthNode(self, root, k): 11 | """ 12 | :type root: TreeNode 13 | :type k: int 14 | :rtype: TreeNode 15 | """ 16 | 17 | if root is None: 18 | return None 19 | 20 | # 1 表示递归处理,0 表示当前我就要处理这个结点 21 | stack = [(1, root)] 22 | 23 | while stack: 24 | type, node = stack.pop() 25 | if type == 0: 26 | k -= 1 27 | if k == 0: 28 | return node 29 | else: 30 | if node.right: 31 | stack.append((1, node.right)) 32 | stack.append((0, node)) 33 | if node.left: 34 | stack.append((1, node.left)) 35 | -------------------------------------------------------------------------------- /codes/python/55-二叉树的深度.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | class Solution: 10 | def treeDepth(self, root): 11 | """ 12 | :type root: TreeNode 13 | :rtype: int 14 | """ 15 | 16 | if root is None: 17 | return 0 18 | 19 | queue = [(1, root)] 20 | res = 0 21 | while queue: 22 | top = queue.pop(0) 23 | cur_depth, node = top[0], top[1] 24 | res = max(res, cur_depth) 25 | if node.left: 26 | queue.append((cur_depth + 1, node.left)) 27 | if node.right: 28 | queue.append((cur_depth + 1, node.right)) 29 | return res 30 | -------------------------------------------------------------------------------- /codes/python/55_2-平衡二叉树-1.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution(object): 9 | flag = 1 10 | 11 | def isBalanced(self, root): 12 | """ 13 | :type root: TreeNode 14 | :rtype: bool 15 | """ 16 | 17 | if root is None: 18 | return True 19 | self.__dfs(root) 20 | return self.flag 21 | 22 | def __dfs(self, node): 23 | """ 24 | 返回以 root 为根的二叉树的高度,如果左右子树其中之一不是 AVL ,则返回 -1 25 | :param node: 26 | :return: 27 | """ 28 | if node is None: 29 | return 0 30 | left = self.__dfs(node.left) 31 | right = self.__dfs(node.right) 32 | 33 | if abs(left - right) > 1: 34 | self.flag = 0 35 | # 这里不能写 return 36 | return max(left, right) + 1 37 | -------------------------------------------------------------------------------- /codes/python/55_2-平衡二叉树.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution(object): 9 | def isBalanced(self, root): 10 | """ 11 | :type root: TreeNode 12 | :rtype: bool 13 | """ 14 | 15 | return self.__helper(root) != -1 16 | 17 | def __helper(self, node): 18 | """ 19 | 返回以 root 为根的二叉树的高度,如果左右子树其中之一不是 AVL ,则返回 -1 20 | :param node: 21 | :return: 22 | """ 23 | if node is None: 24 | return 0 25 | left = self.__helper(node.left) 26 | right = self.__helper(node.right) 27 | 28 | if left == -1 or right == -1 or abs(left - right) > 1: 29 | return -1 30 | return max(left, right) + 1 31 | -------------------------------------------------------------------------------- /codes/python/56-1-数组中只出现一次的两个数.py: -------------------------------------------------------------------------------- 1 | # 一个整型数组里除了两个数字之外,其他的数字都出现了两次。 2 | # 3 | # 请写程序找出这两个只出现一次的数字。 4 | # 5 | # 你可以假设这两个数字一定存在。 6 | # 7 | # 样例 8 | # 输入:[1,2,3,3,4,4] 9 | # 10 | # 输出:[1,2] 11 | 12 | class Solution(object): 13 | def findNumsAppearOnce(self, nums): 14 | """ 15 | :type nums: List[int] 16 | :rtype: List[int] 17 | """ 18 | l = len(nums) 19 | if l < 2: 20 | raise Exception('程序出错') 21 | if l == 2: 22 | return nums 23 | 24 | # 全部相与一遍 25 | xor = 0 26 | for num in nums: 27 | xor ^= num 28 | 29 | # 最末尾的 1 从右向左边数在第几位 30 | counter = 0 31 | while xor & 1 == 0: 32 | xor >>= 1 33 | counter += 1 34 | 35 | res = [0, 0] 36 | for num in nums: 37 | if (num >> counter) & 1 == 1: 38 | res[1] ^= num 39 | else: 40 | res[0] ^= num 41 | return res 42 | 43 | 44 | if __name__ == '__main__': 45 | nums = [1, 2, 3, 3, 4, 4] 46 | solution = Solution() 47 | result = solution.findNumsAppearOnce(nums) 48 | print(result) 49 | -------------------------------------------------------------------------------- /codes/python/56-数字在排序数组中出现的次数.py: -------------------------------------------------------------------------------- 1 | # # 56、数字在排序数组中出现的次数 2 | # 统计一个数字在排序数组中出现的次数。 3 | # 4 | # 例如输入排序数组[1, 2, 3, 3, 3, 3, 4, 5]和数字3,由于3在这个数组中出现了4次,因此输出4。 5 | 6 | 7 | class Solution(object): 8 | 9 | # 返回大于等于 target 的第 1 个数 10 | def get_left(self, nums, target): 11 | # [2,3,4,5,5,5,5,5,5,5] 12 | # [1,1,1,1,1,1,1,1,1,2,3,4,5,5,5,5,5,5,5] 13 | if nums[0] == target: 14 | return 0 15 | l = 1 16 | r = len(nums) 17 | while l < r: 18 | mid = l + (r - l) // 2 19 | if nums[mid] < target: 20 | l = mid + 1 21 | else: 22 | assert nums[mid] >= target 23 | # 不能排除 mid 24 | r = mid 25 | return l 26 | 27 | def getNumberOfK(self, nums, k): 28 | """ 29 | :type nums: list[int] 30 | :type k: int 31 | :rtype: int 32 | """ 33 | size = len(nums) 34 | if size == 0: 35 | return 0 36 | return self.get_left(nums, k + 1) - self.get_left(nums, k) 37 | 38 | 39 | if __name__ == '__main__': 40 | nums = [2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10] 41 | k = 5 42 | solution = Solution() 43 | # result = solution.get_left(nums, 5, ) 44 | # print(result) 45 | 46 | result = solution.getNumberOfK(nums, k) 47 | print(result) 48 | -------------------------------------------------------------------------------- /codes/python/56-数字在排序数组中出现的次数(解法2).py: -------------------------------------------------------------------------------- 1 | # # 56、数字在排序数组中出现的次数 2 | # 统计一个数字在排序数组中出现的次数。 3 | # 4 | # 例如输入排序数组[1, 2, 3, 3, 3, 3, 4, 5]和数字3,由于3在这个数组中出现了4次,因此输出4。 5 | 6 | 7 | class Solution(object): 8 | 9 | def getNumberOfK(self, nums, k): 10 | """ 11 | :type nums: list[int] 12 | :type k: int 13 | :rtype: int 14 | """ 15 | size = len(nums) 16 | if size == 0: 17 | return 0 18 | 19 | # 设置辅助函数,给一个 nums,一个 k,返回大于等于 k 的第一个数的索引 20 | return self.__helper(nums, k + 1) - self.__helper(nums, k) 21 | 22 | def __helper(self, nums, k): 23 | """ 24 | 返回大于等于 k 的第一个数的索引 25 | :param nums: 26 | :param k: 27 | :return: 28 | """ 29 | size = len(nums) 30 | if size == 0: 31 | return 0 32 | 33 | l = 0 34 | # 注意:这里一定要写 size 35 | r = size 36 | while l < r: 37 | mid = l + (r - l) // 2 38 | if nums[mid] >= k: 39 | r = mid 40 | else: 41 | assert nums[mid] < k 42 | # [1,2,3,4,5] 43 | l = mid + 1 44 | return l 45 | 46 | 47 | if __name__ == '__main__': 48 | nums = [2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10] 49 | k = 5 50 | solution = Solution() 51 | # result = solution.get_left(nums, 5, ) 52 | # print(result) 53 | 54 | result = solution.getNumberOfK(nums, k) 55 | print(result) 56 | -------------------------------------------------------------------------------- /codes/python/56-数字在排序数组中出现的次数(解法3-书上的写法).py: -------------------------------------------------------------------------------- 1 | # # 56、数字在排序数组中出现的次数 2 | # 统计一个数字在排序数组中出现的次数。 3 | # 4 | # 例如输入排序数组[1, 2, 3, 3, 3, 3, 4, 5]和数字3,由于3在这个数组中出现了4次,因此输出4。 5 | 6 | 7 | class Solution(object): 8 | 9 | def getNumberOfK(self, nums, k): 10 | """ 11 | :type nums: list[int] 12 | :type k: int 13 | :rtype: int 14 | """ 15 | size = len(nums) 16 | if size == 0: 17 | return 0 18 | 19 | # 设置辅助函数,给一个 nums,一个 k,返回大于等于 k 的第一个数的索引 20 | 21 | k_right = self.__get_right_k(nums, k) 22 | k_left = self.__get_left_k(nums, k) 23 | 24 | if k_right == -1 or k_left == -1: 25 | return 0 26 | 27 | return k_right - k_left + 1 28 | 29 | def __get_right_k(self, nums, k): 30 | # 找到最右边的 index ,使得 nums[index] = k 31 | size = len(nums) 32 | if size == 0: 33 | return -1 34 | l = 0 35 | r = size - 1 36 | while l < r: 37 | mid = l + (r - l + 1) // 2 38 | if nums[mid] <= k: 39 | # [1,2,5,5,5,7] 40 | l = mid 41 | elif nums[mid] > k: 42 | r = mid - 1 43 | if nums[l] != k: 44 | return -1 45 | return l 46 | 47 | def __get_left_k(self, nums, k): 48 | # 找到最左边的 index ,使得 nums[index] = k 49 | size = len(nums) 50 | if size == 0: 51 | return -1 52 | l = 0 53 | r = size - 1 54 | while l < r: 55 | mid = l + (r - l) // 2 56 | if nums[mid] >= k: 57 | r = mid 58 | else: 59 | assert nums[mid] < k 60 | l = mid + 1 61 | if nums[l] != k: 62 | return -1 63 | return l 64 | 65 | 66 | if __name__ == '__main__': 67 | nums = [2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10] 68 | k = 5 69 | solution = Solution() 70 | # result = solution.get_left(nums, 5, ) 71 | # print(result) 72 | 73 | result = solution.getNumberOfK(nums, k) 74 | print(result) 75 | -------------------------------------------------------------------------------- /codes/python/56_2-数组中唯一只出现一次的数字.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findNumberAppearingOnce(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | 8 | res = 0 9 | 10 | for i in range(32): 11 | count = 0 12 | for num in nums: 13 | # 不要忘记 & 1 14 | if (num >> i) & 1: 15 | count += 1 16 | if count % 3: 17 | res += 1 << i 18 | return res 19 | 20 | 21 | if __name__ == '__main__': 22 | nums = [1, 0, 0, 0, 2, 1, 1] 23 | solution = Solution() 24 | result = solution.findNumberAppearingOnce(nums) 25 | print(result) 26 | -------------------------------------------------------------------------------- /codes/python/57-和为 S 的连续正数序列.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findContinuousSequence(self, sum): 3 | """ 4 | :type sum: int 5 | :rtype: List[List[int]] 6 | """ 7 | 8 | res = [] 9 | 10 | left = 1 11 | right = 2 12 | 13 | half = sum // 2 + 1 14 | while left < right <= half: 15 | cur_sum = (left + right) * (right - left + 1) // 2 16 | if cur_sum == sum: 17 | res.append([i for i in range(left, right + 1)]) 18 | right += 1 19 | elif cur_sum < sum: 20 | right += 1 21 | else: 22 | assert cur_sum > sum 23 | left += 1 24 | return res 25 | 26 | 27 | if __name__ == '__main__': 28 | sum = 15 29 | solution = Solution() 30 | result = solution.findContinuousSequence(sum) 31 | print(result) 32 | -------------------------------------------------------------------------------- /codes/python/58_1-翻转单词顺序列.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def reverseWords(self, s): 3 | """ 4 | :type s: str 5 | :rtype: str 6 | """ 7 | 8 | size = len(s) 9 | arr = list(s) 10 | 11 | self.__reverse(arr, 0, size - 1) 12 | 13 | begin = 0 14 | index = 0 15 | while index < size: 16 | if arr[index] == ' ': 17 | self.__reverse(arr, begin, index - 1) 18 | begin = index + 1 19 | index += 1 20 | # 最后还要反转一下 21 | self.__reverse(arr, begin, size - 1) 22 | return ''.join(arr) 23 | 24 | def __reverse(self, arr, left, right): 25 | if left >= right: 26 | return 27 | while left < right: 28 | arr[left], arr[right] = arr[right], arr[left] 29 | left += 1 30 | right -= 1 31 | 32 | 33 | if __name__ == '__main__': 34 | s = "I am a student." 35 | solution = Solution() 36 | result = solution.reverseWords(s) 37 | print(result) 38 | -------------------------------------------------------------------------------- /codes/python/58_2-左旋转字符串.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def leftRotateString(self, s, n): 3 | """ 4 | :type s: str 5 | :type n: int 6 | :rtype: str 7 | """ 8 | 9 | size = len(s) 10 | # 特判 11 | if size == 0 or n % size == 0: 12 | return s 13 | n = n % size 14 | arr = list(s) 15 | self.__reverse(arr, 0, size - 1) 16 | 17 | self.__reverse(arr, 0, size - 1 - n) 18 | self.__reverse(arr, size - n, size - 1) 19 | 20 | return ''.join(arr) 21 | 22 | def __reverse(self, arr, left, right): 23 | if left >= right: 24 | return 25 | while left < right: 26 | arr[left], arr[right] = arr[right], arr[left] 27 | left += 1 28 | right -= 1 29 | 30 | 31 | if __name__ == '__main__': 32 | s = "abcdefg" 33 | n = 2 34 | solution = Solution() 35 | result = solution.leftRotateString(s, n) 36 | print(result) 37 | -------------------------------------------------------------------------------- /codes/python/59-滑动窗口的最大值.py: -------------------------------------------------------------------------------- 1 | # 同 LeetCode 第 239 题,传送门:滑动窗口最大值。 2 | class Solution: 3 | def maxSlidingWindow(self, nums, k): 4 | """ 5 | :type nums: List[int] 6 | :type k: int 7 | :rtype: List[int] 8 | """ 9 | 10 | # 关键:如果后进来一个数,前面的元素比它小 11 | # 那么前面的元素就永远不可能是"滑动窗口中的最大值" 12 | 13 | l = len(nums) 14 | if l == 0 or k <= 0: 15 | return [] 16 | 17 | res = [] 18 | window = [] 19 | for i in range(l): 20 | 21 | # 考虑什么时候,要把最大移除 22 | # 左边界划出的时候,应该是 window.pop(0) 23 | # [0,1,2,3,4] 24 | # [ i] 25 | # window[0] == i - k 这个条件特别容易忽略 26 | if i >= k and window[0] == i - k: 27 | window.pop(0) 28 | # 考虑把不可能是最大的元素全部 kill 掉 29 | while window and nums[i] >= nums[window[-1]]: 30 | window.pop() 31 | window.append(i) 32 | 33 | # 什么时候有滑动窗口呢? 34 | if i >= k - 1: 35 | res.append(nums[window[0]]) 36 | return res 37 | 38 | 39 | if __name__ == '__main__': 40 | nums = [1, 3, -1, -3, 5, 3, 6, 7] 41 | k = 3 42 | 43 | solution = Solution() 44 | result = solution.maxSlidingWindow(nums, k) 45 | print(result) 46 | -------------------------------------------------------------------------------- /codes/python/6-从尾到头打印链表.py: -------------------------------------------------------------------------------- 1 | # 17. 从尾到头打印链表 2 | # 输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。 3 | # 返回的结果用数组存储。 4 | 5 | 6 | # Definition for singly-linked list. 7 | # class ListNode(object): 8 | # def __init__(self, x): 9 | # self.val = x 10 | # self.next = None 11 | class Solution(object): 12 | 13 | def printListReversingly(self, head): 14 | """ 15 | :type head: ListNode 16 | :rtype: List[int] 17 | """ 18 | p = head 19 | stack = [] 20 | while p: 21 | stack.insert(0, p.val) 22 | p = p.next 23 | return stack 24 | -------------------------------------------------------------------------------- /codes/python/6-从尾到头打印链表(使用递归)-错误写法.py: -------------------------------------------------------------------------------- 1 | # 17. 从尾到头打印链表 2 | # 输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。 3 | # 返回的结果用数组存储。 4 | 5 | 6 | # Definition for singly-linked list. 7 | # class ListNode(object): 8 | # def __init__(self, x): 9 | # self.val = x 10 | # self.next = None 11 | class Solution(object): 12 | 13 | def printListReversingly(self, head): 14 | """ 15 | :type head: ListNode 16 | :rtype: List[int] 17 | """ 18 | res = [] 19 | self.helper(res, head) 20 | return res 21 | 22 | def helper(self, res, listnode): 23 | if listnode is None: 24 | return 25 | 26 | if listnode.next is None: 27 | res.append(listnode.val) 28 | self.helper(res, listnode.next) 29 | -------------------------------------------------------------------------------- /codes/python/6-从尾到头打印链表(使用递归).py: -------------------------------------------------------------------------------- 1 | # 17. 从尾到头打印链表 2 | # 输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。 3 | # 返回的结果用数组存储。 4 | 5 | 6 | # Definition for singly-linked list. 7 | # class ListNode(object): 8 | # def __init__(self, x): 9 | # self.val = x 10 | # self.next = None 11 | class Solution(object): 12 | 13 | def printListReversingly(self, head): 14 | """ 15 | :type head: ListNode 16 | :rtype: List[int] 17 | """ 18 | res = [] 19 | self.helper(res, head) 20 | return res 21 | 22 | def helper(self, res, listnode): 23 | if listnode is None: 24 | return 25 | # 应该先判断下一个结点是否为空,如果不为空,则递归调用,在回溯的时候,才添加到结果中 26 | if listnode.next: 27 | self.helper(res, listnode.next) 28 | # 回溯时添加 29 | res.append(listnode.val) 30 | -------------------------------------------------------------------------------- /codes/python/6-从尾到头打印链表(真正用栈).py: -------------------------------------------------------------------------------- 1 | # 17. 从尾到头打印链表 2 | # 输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。 3 | # 返回的结果用数组存储。 4 | 5 | 6 | # Definition for singly-linked list. 7 | # class ListNode(object): 8 | # def __init__(self, x): 9 | # self.val = x 10 | # self.next = None 11 | class Solution(object): 12 | 13 | def printListReversingly(self, head): 14 | """ 15 | :type head: ListNode 16 | :rtype: List[int] 17 | """ 18 | p = head 19 | stack = [] 20 | while p: 21 | stack.append(p.val) 22 | p = p.next 23 | return stack[::-1] 24 | -------------------------------------------------------------------------------- /codes/python/60-n 个骰子的点数.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def numberOfDice(self, n): 3 | """ 4 | :type n: int 5 | :rtype: List[int] 6 | """ 7 | dp = [0 for _ in range(6 * n + 1)] 8 | 9 | # 动归数组初始值,表示 1 个骰子扔出 1-6 的可能数都为 1 10 | for i in range(1, 7): 11 | dp[i] = 1 12 | # 表示仍第 2 个骰子到第 n 个骰子 13 | for i in range(2, n + 1): 14 | # 从后向前写 15 | for j in range(6 * i, -1, -1): 16 | dp[j] = 0 17 | # 最后一个骰子可以扔 1 - 6 点 18 | for k in range(6, 0, -1): 19 | if j - k < 0: 20 | continue 21 | dp[j] += dp[j - k] 22 | # 扔 n 个骰子的和为 [n, 6 * n] 23 | return dp[n:] 24 | 25 | 26 | if __name__ == '__main__': 27 | solution = Solution() 28 | n = 2 29 | result = solution.numberOfDice(n) 30 | print(result) 31 | -------------------------------------------------------------------------------- /codes/python/61-扑克牌的顺子.py: -------------------------------------------------------------------------------- 1 | # 61 、扑克牌顺子 2 | 3 | 4 | class Solution(object): 5 | def isContinuous(self, numbers): 6 | """ 7 | :type numbers: List[int] 8 | :rtype: bool 9 | """ 10 | size = len(numbers) 11 | if size != 5: 12 | return False 13 | # 最小值和最大值都设置成一个不可能取到的值 14 | min_val = 14 15 | max_val = -1 16 | 17 | flag = 0 18 | for num in numbers: 19 | if not 0 <= num <= 13: 20 | return False 21 | if num == 0: 22 | continue 23 | # 右移:看看这一位是不是用过了 24 | if (flag >> num) & 1 == 1: 25 | return False 26 | 27 | # 左移:表示这一位我现在要占用 28 | flag = flag | (1 << num) 29 | 30 | min_val = min(min_val, num) 31 | max_val = max(max_val, num) 32 | if max_val - min_val >= 5: 33 | return False 34 | return True 35 | -------------------------------------------------------------------------------- /codes/python/62-圆圈中最后剩下的数字.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def lastRemaining(self, n, m): 4 | # 特判 5 | if n == 0 and m == 0: 6 | return -1 7 | 8 | l = [i for i in range(n)] 9 | bt = 0 10 | while len(l) > 1: 11 | 12 | # 在这一行模拟约瑟夫环操作 13 | # 1、m - 1 :因为当前数字算 1 个,走 m - 1 步 14 | # 2、len(l):每次删去一个数,所以得动态取 15 | bt = (bt + m - 1) % len(l) 16 | 17 | l.pop(bt) 18 | return l[0] 19 | 20 | 21 | if __name__ == '__main__': 22 | n = 5 23 | m = 3 24 | solution = Solution() 25 | result = solution.lastRemaining(n, m) 26 | print(result) 27 | -------------------------------------------------------------------------------- /codes/python/62-圆圈中最后剩下的数字(练习).py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def lastRemaining(self, n, m): 4 | if n == 0 and m == 0: 5 | return -1 6 | 7 | l = list(range(n)) 8 | bt = 0 9 | while len(l) > 1: 10 | bt = (bt + m - 1) % len(l) 11 | l.pop(bt) 12 | 13 | return l[0] 14 | 15 | 16 | if __name__ == '__main__': 17 | n = 1 18 | m = 1 19 | solution = Solution() 20 | result = solution.lastRemaining(n, m) 21 | print(result) 22 | -------------------------------------------------------------------------------- /codes/python/63-股票的最大利润.py: -------------------------------------------------------------------------------- 1 | # 83、股票的最大利润 2 | # 3 | # 4 | # 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖交易该股票可能获得的利润是多少? 5 | # 6 | # 例如一只股票在某些时间节点的价格为[9, 11, 8, 5, 7, 12, 16, 14]。 7 | # 8 | # 如果我们能在价格为5的时候买入并在价格为16时卖出,则能收获最大的利润11。 9 | # 10 | # 样例 11 | # 输入:[9, 11, 8, 5, 7, 12, 16, 14] 12 | # 13 | # 输出:11 14 | 15 | 16 | class Solution(object): 17 | def maxDiff(self, nums): 18 | """ 19 | :type nums: List[int] 20 | :rtype: int 21 | """ 22 | l = len(nums) 23 | if l == 0: 24 | return 0 25 | 26 | min_val = nums[0] 27 | max_profit = 0 28 | for i in range(1, l): 29 | min_val = min(min_val, nums[i]) 30 | max_profit = max(max_profit, nums[i] - min_val) 31 | return max_profit 32 | -------------------------------------------------------------------------------- /codes/python/63-股票的最大利润(贪心算法).py: -------------------------------------------------------------------------------- 1 | # 83、股票的最大利润 2 | # 3 | # 4 | # 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖交易该股票可能获得的利润是多少? 5 | # 6 | # 例如一只股票在某些时间节点的价格为[9, 11, 8, 5, 7, 12, 16, 14]。 7 | # 8 | # 如果我们能在价格为5的时候买入并在价格为16时卖出,则能收获最大的利润11。 9 | # 10 | # 样例 11 | # 输入:[9, 11, 8, 5, 7, 12, 16, 14] 12 | # 13 | # 输出:11 14 | 15 | # 不能使用贪心算法,区别于 122. 买卖股票的最佳时机 II 16 | 17 | class Solution(object): 18 | def maxDiff(self, nums): 19 | """ 20 | :type nums: List[int] 21 | :rtype: int 22 | """ 23 | l = len(nums) 24 | if l == 0: 25 | return 0 26 | max_profit = 0 27 | for i in range(1, l): 28 | if nums[i] - nums[i - 1] > 0: 29 | max_profit += (nums[i] - nums[i - 1]) 30 | return max_profit 31 | 32 | 33 | if __name__ == '__main__': 34 | nums = [9, 11, 8, 5, 7, 12, 16, 14] 35 | solution = Solution() 36 | result = solution.maxDiff(nums) 37 | print(result) 38 | -------------------------------------------------------------------------------- /codes/python/64-求 1 + 2 + 3 + ... + n.py: -------------------------------------------------------------------------------- 1 | # 64、求 1 + 2 + 3 + ... + n 2 | 3 | class Solution(object): 4 | def getSum(self, n): 5 | """ 6 | :type n: int 7 | :rtype: int 8 | """ 9 | 10 | return (n ** 2 + n) >> 1 11 | 12 | 13 | if __name__ == '__main__': 14 | n = 1000 15 | solution = Solution() 16 | result = solution.getSum(n) 17 | print(result) 18 | -------------------------------------------------------------------------------- /codes/python/65-不用加减乘除做加法-负数处理.py: -------------------------------------------------------------------------------- 1 | # 65、不用加减乘除做加法 2 | 3 | class Solution(object): 4 | def add(self, num1, num2): 5 | """ 6 | :type num1: int 7 | :type num2: int 8 | :rtype: int 9 | """ 10 | while num2 != 0: 11 | temp = num1 ^ num2 12 | num2 = (num1 & num2) << 1 13 | num1 = temp & 0xFFFFFFFF 14 | return num1 if num1 >> 31 == 0 else num1 - (1 << 32) 15 | 16 | 17 | if __name__ == '__main__': 18 | num1 = 5 19 | num2 = -6 20 | solution = Solution() 21 | result = solution.add(num1, num2) 22 | print(result) 23 | 24 | -------------------------------------------------------------------------------- /codes/python/65-不用加减乘除做加法-负数处理1.py: -------------------------------------------------------------------------------- 1 | # 65、不用加减乘除做加法 2 | 3 | 4 | # 因为 Python 5 | 6 | class Solution(object): 7 | def add(self, num1, num2): 8 | """ 9 | :type num1: int 10 | :type num2: int 11 | :rtype: int 12 | """ 13 | 14 | while True: 15 | # 不进位加法 16 | s = num1 ^ num2 17 | # 计算进位 18 | carry = num1 & num2 19 | 20 | # 手动把高于 32 位的部分变成 0 21 | num1 = s & 0xFFFFFFFF 22 | num2 = carry << 1 23 | 24 | if carry == 0: 25 | break 26 | # 如果是正数和 0 ,就直接返回这个正数好了 27 | if num1 >> 31 == 0: 28 | return num1 29 | # 如果是负数 30 | return num1 - (1 << 32) 31 | 32 | 33 | if __name__ == '__main__': 34 | num1 = 5 35 | num2 = -6 36 | solution = Solution() 37 | result = solution.add(num1, num2) 38 | print(result) 39 | 40 | print(0x7fffffff) 41 | -------------------------------------------------------------------------------- /codes/python/65-不用加减乘除做加法.py: -------------------------------------------------------------------------------- 1 | # 65、不用加减乘除做加法 2 | 3 | class Solution(object): 4 | def add(self, num1, num2): 5 | """ 6 | :type num1: int 7 | :type num2: int 8 | :rtype: int 9 | """ 10 | # 特判 11 | if num1 == 0 or num2 == 0: 12 | return max(num1, num2) 13 | 14 | while True: 15 | # 先做不进位加法 16 | s = num1 ^ num2 17 | # 再计算进位 18 | carry = num1 & num2 19 | if carry == 0: 20 | return s 21 | num1 = s 22 | num2 = carry << 1 23 | 24 | 25 | if __name__ == '__main__': 26 | num1 = 100 27 | num2 = 200 28 | solution = Solution() 29 | result = solution.add(num1, num2) 30 | print(result) 31 | -------------------------------------------------------------------------------- /codes/python/65-不用加减乘除做加法(位运算加法器).py: -------------------------------------------------------------------------------- 1 | # 65、不用加减乘除做加法 2 | 3 | class Solution(object): 4 | def add(self, num1, num2): 5 | """ 6 | :type num1: int 7 | :type num2: int 8 | :rtype: int 9 | """ 10 | # 特判 11 | if num1 == 0 or num2 == 0: 12 | return max(num1, num2) 13 | 14 | res = 0 15 | # 标杆 16 | tmp = 1 17 | # 进位 18 | carry = 0 19 | 20 | for i in range(32): 21 | a = num1 & tmp 22 | b = num2 & tmp 23 | # 不进位的和 24 | s_ = (a ^ b) ^ carry 25 | # 下面计算进位,三者之中,任意两者同为 1 的时候,就可以进位 26 | c_cout = (a & b) | (a & carry) | (b & carry) 27 | carry = c_cout << 1 28 | tmp <<= 1 29 | res += s_ 30 | if res >> 31 == 0: 31 | return res 32 | 33 | return res - (1 << 32) 34 | 35 | 36 | if __name__ == '__main__': 37 | num1 = -3 38 | num2 = -2 39 | 40 | solution = Solution() 41 | result = solution.add(num1, num2) 42 | print(result) 43 | 44 | # print(bin(-1 & 0b1111111111111111)) 45 | # print(-1 & 0xffffffff) 46 | -------------------------------------------------------------------------------- /codes/python/65-不用加减乘除做加法(全加器2).py: -------------------------------------------------------------------------------- 1 | # 65、不用加减乘除做加法 2 | 3 | class Solution(object): 4 | def add(self, num1, num2): 5 | """ 6 | :type num1: int 7 | :type num2: int 8 | :rtype: int 9 | """ 10 | # 特判 11 | if num1 == 0 or num2 == 0: 12 | return max(num1, num2) 13 | 14 | res = 0 15 | # 进位 16 | carry = 0 17 | for i in range(32): 18 | a = num1 & (1 << i) 19 | b = num2 & (1 << i) 20 | # 不进位的和 21 | s_ = (a ^ b) ^ carry 22 | # 下面计算进位,三者之中,任意两者同为 1 的时候,就可以进位 23 | carry = (a & b) | (a & carry) | (b & carry) 24 | carry <<= 1 25 | res += s_ 26 | if res >> 31 == 0: 27 | return res 28 | return res - (1 << 32) 29 | 30 | 31 | if __name__ == '__main__': 32 | num1 = -3 33 | num2 = -2 34 | 35 | solution = Solution() 36 | result = solution.add(num1, num2) 37 | print(result) 38 | 39 | # print(bin(-1 & 0b1111111111111111)) 40 | # print(-1 & 0xffffffff) 41 | -------------------------------------------------------------------------------- /codes/python/66-构建乘积数组.py: -------------------------------------------------------------------------------- 1 | # 66、构建乘积数组 2 | 3 | class Solution(object): 4 | def multiply(self, A): 5 | """ 6 | :type A: List[int] 7 | :rtype: List[int] 8 | """ 9 | 10 | l = len(A) 11 | if l == 0: 12 | return [] 13 | b = [None for _ in range(l)] 14 | 15 | b[0] = 1 16 | # 计算下三角连乘的结果 17 | for i in range(1, l): 18 | b[i] = b[i - 1] * A[i - 1] 19 | 20 | temp = 1 21 | for i in range(l - 2, -1, -1): 22 | temp *= A[i + 1] 23 | b[i] *= temp 24 | return b 25 | -------------------------------------------------------------------------------- /codes/python/67-把字符串转换成整数.py: -------------------------------------------------------------------------------- 1 | # 67、把字符串转换成整数 2 | 3 | 4 | class Solution(object): 5 | def strToInt(self, str): 6 | """ 7 | :type str: str 8 | :rtype: int 9 | """ 10 | 11 | # 去掉左右空格 12 | s = str.strip() 13 | 14 | l = len(s) 15 | if l == 0: 16 | return 0 17 | 18 | # 遍历指针 19 | index = 0 20 | # 符号 21 | sign = 1 22 | # 第 1 位符号位 23 | s_sign = s[0] 24 | 25 | # 最终结果 26 | res = 0 27 | 28 | INT_MIN = -1 << 31 29 | INT_MAX = (1 << 31) - 1 30 | 31 | # 符号位是正或负号的时候 index 都加 1 32 | if s_sign == '+': 33 | index += 1 34 | elif s_sign == '-': 35 | index += 1 36 | sign = -1 37 | 38 | for i in range(index, l): 39 | c = s[i] 40 | if c.isdigit(): 41 | cint = ord(c) - ord('0') 42 | res = res * 10 + cint 43 | if res * sign > INT_MAX: 44 | break 45 | else: 46 | break 47 | 48 | res *= sign 49 | 50 | if res > INT_MAX: 51 | return INT_MAX 52 | elif res < INT_MIN: 53 | return INT_MIN 54 | return res 55 | 56 | 57 | if __name__ == '__main__': 58 | solution = Solution() 59 | str = '2147483647' 60 | result = solution.strToInt(str) 61 | print(result) 62 | -------------------------------------------------------------------------------- /codes/python/68-二叉树最近公共祖先.py: -------------------------------------------------------------------------------- 1 | # 68、树中两个节点的最近公共祖先 2 | # Definition for a binary tree node. 3 | # class TreeNode(object): 4 | # def __init__(self, x): 5 | # self.val = x 6 | # self.left = None 7 | # self.right = None 8 | 9 | class Solution(object): 10 | def lowestCommonAncestor(self, root, p, q): 11 | """ 12 | :type root: TreeNode 13 | :type p: TreeNode 14 | :type q: TreeNode 15 | :rtype: TreeNode 16 | """ 17 | 18 | if root is None: 19 | return None 20 | if root == p or root == q: 21 | return root 22 | left = self.lowestCommonAncestor(root.left, p, q) 23 | right = self.lowestCommonAncestor(root.right, p, q) 24 | if left and right: 25 | return root 26 | if left is None: 27 | return right 28 | else: 29 | return left 30 | -------------------------------------------------------------------------------- /codes/python/7-重建二叉树.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | class Solution(object): 10 | def buildTree(self, preorder, inorder): 11 | """ 12 | 返回构造的 TreeNode 根结点 13 | :type preorder: List[int] 14 | :type inorder: List[int] 15 | :rtype: TreeNode 16 | """ 17 | # 在编码过程中,一定要保证 len(pre) == len(tin),否则逻辑一定不正确 18 | if len(preorder) == 0: 19 | return None 20 | if len(preorder) == 1: 21 | # 这里要返回结点,而不是返回具体的数 22 | return TreeNode(preorder[0]) 23 | root = TreeNode(preorder[0]) 24 | # 直接得到在中序遍历中的位置,下面算好偏移量就好了,如果容易算错,记得拿具体例子 25 | pos = inorder.index(preorder[0]) 26 | root.left = self.buildTree(preorder[1:pos + 1], inorder[:pos]) 27 | root.right = self.buildTree(preorder[pos + 1:], inorder[pos + 1:]) 28 | return root 29 | -------------------------------------------------------------------------------- /codes/python/8-二叉树的下一个结点.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | self.father = None 8 | 9 | 10 | class Solution(object): 11 | def inorderSuccessor(self, q): 12 | """ 13 | :type q: TreeNode 14 | :rtype: TreeNode 15 | """ 16 | 17 | if q is None: 18 | return None 19 | 20 | # 分类讨论1:如果这个结点有右子树,返回这个右子树的最小者 21 | if q.right: 22 | node = q.right 23 | while node.left: 24 | node = node.left 25 | return node 26 | # 分类讨论2:如果这个结点没有右子树,向上追溯,追到父亲结点的左结点是自己 27 | while q.father: 28 | if q.father.left == q: 29 | return q.father 30 | q = q.father 31 | return None 32 | -------------------------------------------------------------------------------- /codes/python/9-1-用两个栈实现队列.py: -------------------------------------------------------------------------------- 1 | class MyQueue(object): 2 | 3 | def __init__(self): 4 | """ 5 | Initialize your data structure here. 6 | """ 7 | 8 | self.stack1 = [] 9 | self.stack2 = [] 10 | 11 | def push(self, x): 12 | """ 13 | Push element x to the back of queue. 14 | :type x: int 15 | :rtype: void 16 | """ 17 | self.stack1.append(x) 18 | 19 | def __shift(self): 20 | if len(self.stack2) == 0: 21 | while self.stack1: 22 | self.stack2.append(self.stack1.pop()) 23 | 24 | def pop(self): 25 | """ 26 | Removes the element from in front of queue and returns that element. 27 | :rtype: int 28 | """ 29 | self.__shift() 30 | return self.stack2.pop() 31 | 32 | def peek(self): 33 | """ 34 | Get the front element. 35 | :rtype: int 36 | """ 37 | self.__shift() 38 | return self.stack2[-1] 39 | 40 | def empty(self): 41 | """ 42 | Returns whether the queue is empty. 43 | :rtype: bool 44 | """ 45 | return len(self.stack1) == 0 and len(self.stack2) == 0 46 | 47 | # Your MyQueue object will be instantiated and called as such: 48 | # obj = MyQueue() 49 | # obj.push(x) 50 | # param_2 = obj.pop() 51 | # param_3 = obj.peek() 52 | # param_4 = obj.empty() 53 | -------------------------------------------------------------------------------- /codes/python/9-2-用队列实现栈.py: -------------------------------------------------------------------------------- 1 | class MyStack: 2 | 3 | def __init__(self): 4 | """ 5 | Initialize your data structure here. 6 | """ 7 | 8 | self.queue = [] 9 | 10 | def push(self, x): 11 | """ 12 | Push element x onto stack. 13 | :type x: int 14 | :rtype: void 15 | """ 16 | self.queue.append(x) 17 | # 将队列中前面已经逆序的元素放在 x 元素后面,使得整体逆序 18 | for _ in range(len(self.queue) - 1): 19 | ele = self.queue.pop(0) 20 | self.queue.append(ele) 21 | 22 | def pop(self): 23 | """ 24 | Removes the element on top of the stack and returns that element. 25 | :rtype: int 26 | """ 27 | if self.queue: 28 | return self.queue.pop(0) 29 | 30 | def top(self): 31 | """ 32 | Get the top element. 33 | :rtype: int 34 | """ 35 | if self.queue: 36 | return self.queue[0] 37 | 38 | def empty(self): 39 | """ 40 | Returns whether the stack is empty. 41 | :rtype: bool 42 | """ 43 | return len(self.queue) == 0 44 | 45 | # Your MyStack object will be instantiated and called as such: 46 | # obj = MyStack() 47 | # obj.push(x) 48 | # param_2 = obj.pop() 49 | # param_3 = obj.top() 50 | # param_4 = obj.empty() 51 | -------------------------------------------------------------------------------- /codes/python/数组中数值和下标相等的元素.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def getNumberSameAsIndex(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | 8 | # 使用二分法 9 | size = len(nums) 10 | l = 0 11 | r = size - 1 12 | 13 | while l < r: 14 | mid = l + (r - l) // 2 15 | if nums[mid] < mid: 16 | l = mid + 1 17 | else: 18 | assert nums[mid] >= mid 19 | r = mid 20 | return l if nums[l] == l else -1 21 | 22 | 23 | if __name__ == '__main__': 24 | solution = Solution() 25 | nums = [-3, -1, 1, 3, 5] 26 | result = solution.getNumberSameAsIndex(nums) 27 | print(result) 28 | -------------------------------------------------------------------------------- /codes/python/题号未知-删除链表中的结点.py: -------------------------------------------------------------------------------- 1 | # 28. 在O(1)时间删除链表结点 2 | # 给定单向链表的一个节点指针,定义一个函数在O(1)时间删除该结点。 3 | # 4 | # 假设链表一定存在,并且该节点一定不是尾节点。 5 | # Definition for singly-linked list. 6 | class ListNode(object): 7 | def __init__(self, x): 8 | self.val = x 9 | self.next = None 10 | 11 | 12 | class Solution(object): 13 | def deleteNode(self, node): 14 | """ 15 | :type node: ListNode 16 | :rtype: void 17 | """ 18 | next = node.next 19 | node.val = next.val 20 | node.next = next.next 21 | next.next = None 22 | --------------------------------------------------------------------------------