diff --git a/1.txt b/1.txt new file mode 100644 index 0000000..bd41cba --- /dev/null +++ b/1.txt @@ -0,0 +1 @@ +12345 \ No newline at end of file diff --git a/README b/README deleted file mode 100644 index e5fef5d..0000000 --- a/README +++ /dev/null @@ -1,7 +0,0 @@ -初学python基础语法+基本数据结构+基础算法 -重刷leetcode关于所学内容的题目,用代码尽量表达清楚自己的思路 -依照数据结构从易到难--->基础算法的顺序重新解答,并总结规律技巧 -如果是基础的数据结构,则按解题难度的下限区分 -首轮总结将于完成 链表数组队列栈堆树等基本数据结构和回溯动态规划深度优先遍历广度优先遍历贪心算法 这些基本数据结构和算法题目后结束 -1.链表 - diff --git "a/\345\210\235\350\257\206\344\275\215\350\277\220\347\256\227/63\344\270\215\345\220\214\350\267\257\345\276\2042" "b/\345\210\235\350\257\206\344\275\215\350\277\220\347\256\227/63\344\270\215\345\220\214\350\267\257\345\276\2042" deleted file mode 100644 index eb91ada..0000000 --- "a/\345\210\235\350\257\206\344\275\215\350\277\220\347\256\227/63\344\270\215\345\220\214\350\267\257\345\276\2042" +++ /dev/null @@ -1,58 +0,0 @@ -# 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 -# 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 -# 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径? -# 网格中的障碍物和空位置分别用 1 和 0 来表示。 -# 说明:m 和 n 的值均不超过 100。 -# 示例 1: -# 输入: -# [ -#   [0,0,0], -#   [0,1,0], -#   [0,0,0] -# ] -# 输出: 2 -# 解释: -# 3x3 网格的正中间有一个障碍物。 -# 从左上角到右下角一共有 2 条不同的路径: -# 1. 向右 -> 向右 -> 向下 -> 向下 -# 2. 向下 -> 向下 -> 向右 -> 向右 -# def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: - - -# 思路:这道题明显是62题的难度提高的版本, 在62题的基础上增加了'障碍'这个概念 -# 不过其实影响并不大, 有'障碍'说明该点将无法通行, 所以只需要在计数时 -# 不对'障碍'点进行计数即可 -# 一样使用自底向上的动态规划方式, 由于这里使用0和1来表示障碍 -# 所以会用位运算来转换 -# ^ 表示两个数相同返回0 -# & 表示两个数都为1, 才返回1 -# | 表示只要有一个数为1, 返回1 - - -class Solution: - def uniquePathsWithObstacles(self, obstacleGrid): - d = len(obstacleGrid) - b = len(obstacleGrid[0]) - if obstacleGrid[0][0]: - return 0 - for i in range(d): - for j in range(b): - # 因为初始为1的格子是障碍, 我将把障碍格子的值修改为0 - # 使用 ^1 , 如果格子原来是0, 那么返回1(因为0和1不同, 不同返回1) - # 如果格子原来是1, 那么返回0(因为1和1相同, 相同返回0) - obstacleGrid[i][j] = obstacleGrid[i][j] ^ 1 - for i in range(1, d): - # 排除第一列的障碍 - # 如果上一个格子或者这一个格子不是都为1的话, 那么这个格子不能通行 - # 所以要求都为1才为1(可通行) - obstacleGrid[i][0] = obstacleGrid[i-1][0] & obstacleGrid[i][0] & 1 - for j in range(1, b): - # 排除第一行的障碍 - # 如果左一个格子或者这一个格子不是都为1的话, 那么这个格子不能通行 - # 所以要求都为1才为1(可通行) - obstacleGrid[0][j] = obstacleGrid[0][j-1] & obstacleGrid[0][j] & 1 - for i in range(1, d): - for j in range(1, b): - if obstacleGrid[i][j]: - obstacleGrid[i][j] = obstacleGrid[i - 1][j] + obstacleGrid[i][j - 1] - return obstacleGrid[-1][-1] diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/120\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204" "b/\345\212\250\346\200\201\350\247\204\345\210\222/120\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204" deleted file mode 100644 index df7d3fb..0000000 --- "a/\345\212\250\346\200\201\350\247\204\345\210\222/120\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204" +++ /dev/null @@ -1,26 +0,0 @@ -# 给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。 -# 例如,给定三角形: -# [ -# [2], -# [3,4], -# [6,5,7], -# [4,1,8,3] -# ] -# 自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。 -# 说明: -# 如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。 - - -# 思路:自底向上的使用动态规划, 每个格子储存从底部向上遇到的两种可行方案中路径和最小的一种的结果 -# 然后上一层继续进行判断, 直至结束 -# 原地进行计算和储存 - - -class Solution: - def minimumTotal(self, triangle): - size = len(triangle) - dp = triangle - for i in range(size - 2, -1, -1): - for j in range(i+1): - dp[i][j] += min(dp[i+1][j], dp[i+1][j+1]) - return dp[0][0] diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/62\344\270\215\345\220\214\350\267\257\345\276\204" "b/\345\212\250\346\200\201\350\247\204\345\210\222/62\344\270\215\345\220\214\350\267\257\345\276\204" deleted file mode 100644 index 6a262bf..0000000 --- "a/\345\212\250\346\200\201\350\247\204\345\210\222/62\344\270\215\345\220\214\350\267\257\345\276\204" +++ /dev/null @@ -1,36 +0,0 @@ -# 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 -# 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 -# 问总共有多少条不同的路径? -# 例如,上图是一个7 x 3 的网格。有多少可能的路径? -# 说明:m 和 n 的值均不超过 100。 -# 示例 1: -# 输入: m = 3, n = 2 -# 输出: 3 -# 解释: -# 从左上角开始,总共有 3 条路径可以到达右下角。 -# 1. 向右 -> 向右 -> 向下 -# 2. 向右 -> 向下 -> 向右 -# 3. 向下 -> 向右 -> 向右 -# 示例 2: -# 输入: m = 7, n = 3 -# 输出: 28 -# def uniquePaths(self, m: int, n: int) -> int: - - -# 思路: 这道题目明显是较简单的动态规划, 由于在图中没有禁止通行的点 -# 所以只需要直接判断他们的可移动路径 -# 一个格子如果在他的左和上方都有格子, 那么这个格子的可移动路径必然是 -# 左格子的可移动路径与上格子的可移动路径之和 -# f(x, y) = f(x-1, y) + f(x, y-1) -# 这样一看很像递归的斐波那契数列的写法 -# 事实上如果我们在这个基础上进行记忆化搜索的话其实已经可以算是动态规划了 -# 但是我比较喜欢自底向上的使用动态规划的思想 - - -class Solution: - def uniquePaths(self, m, n): - dp = [[1] * m for j in range(n)] - for i in range(1, n): - for j in range(1, m): - dp[i][j] = dp[i-1][j] + dp[i][j-1] - return dp[-1][-1] diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/63\344\270\215\345\220\214\350\267\257\345\276\2042" "b/\345\212\250\346\200\201\350\247\204\345\210\222/63\344\270\215\345\220\214\350\267\257\345\276\2042" deleted file mode 100644 index 10ae619..0000000 --- "a/\345\212\250\346\200\201\350\247\204\345\210\222/63\344\270\215\345\220\214\350\267\257\345\276\2042" +++ /dev/null @@ -1,46 +0,0 @@ -# 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 -# 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 -# 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径? -# 网格中的障碍物和空位置分别用 1 和 0 来表示。 -# 说明:m 和 n 的值均不超过 100。 -# 示例 1: -# 输入: -# [ -#   [0,0,0], -#   [0,1,0], -#   [0,0,0] -# ] -# 输出: 2 -# 解释: -# 3x3 网格的正中间有一个障碍物。 -# 从左上角到右下角一共有 2 条不同的路径: -# 1. 向右 -> 向右 -> 向下 -> 向下 -# 2. 向下 -> 向下 -> 向右 -> 向右 -# def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: - - -# 思路:这道题明显是62题的难度提高的版本, 在62题的基础上增加了'障碍'这个概念 -# 不过其实影响并不大, 有'障碍'说明该点将无法通行, 所以只需要在计数时 -# 不对'障碍'点进行计数即可 -# 一样使用自底向上的动态规划方式, 由于这里使用0和1来表示障碍 -# 所以会用位运算来转换 - - -class Solution: - def uniquePathsWithObstacles(self, obstacleGrid): - d = len(obstacleGrid) - b = len(obstacleGrid[0]) - if obstacleGrid[0][0]: - return 0 - for i in range(d): - for j in range(b): - obstacleGrid[i][j] = obstacleGrid[i][j] ^ 1 - for i in range(1, d): - obstacleGrid[i][0] = obstacleGrid[i-1][0] & obstacleGrid[i][0] & 1 - for j in range(1, b): - obstacleGrid[0][j] = obstacleGrid[0][j-1] & obstacleGrid[0][j] & 1 - for i in range(1, d): - for j in range(1, b): - if obstacleGrid[i][j]: - obstacleGrid[i][j] = obstacleGrid[i - 1][j] + obstacleGrid[i][j - 1] - return obstacleGrid[-1][-1] diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/64\347\237\251\351\230\265\344\270\255\347\232\204\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214" "b/\345\212\250\346\200\201\350\247\204\345\210\222/64\347\237\251\351\230\265\344\270\255\347\232\204\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214" deleted file mode 100644 index ec12031..0000000 --- "a/\345\212\250\346\200\201\350\247\204\345\210\222/64\347\237\251\351\230\265\344\270\255\347\232\204\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214" +++ /dev/null @@ -1,33 +0,0 @@ -# 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 -# 说明:每次只能向下或者向右移动一步。 -# 示例: -# 输入: -# [ -#   [1,3,1], -# [1,5,1], -# [4,2,1] -# ] -# 输出: 7 -# 解释: 因为路径 1→3→1→1→1 的总和最小。 -# def minPathSum(self, grid: List[List[int]]) -> int: - - -# 思路:这是一道典型的要使用动态规划的题目, 原因是这道题中前后的数字是有关联的 -# 并且涉及最优选择, 所以这里可以使用动态规划的算法思想 -# 并且我将使用自底向上的思路进行解答 - - -class Solution: - def minPathSum(self, grid): - if grid == []: - return 0 - d = len(grid) - b = len(grid[0]) - for i in range(1, d): - grid[i][0] += grid[i-1][0] - for j in range(1, b): - grid[0][j] += grid[0][j-1] - for i in range(1, d): - for j in range(1, b): - grid[i][j] += min(grid[i-1][j], grid[i][j-1]) - return grid[-1][-1] diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\212\250\346\200\201\350\247\204\345\210\222\344\271\213\350\277\236\347\273\255/53\346\234\200\345\244\247\350\277\236\347\273\255\345\255\220\345\272\217\345\222\214" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\212\250\346\200\201\350\247\204\345\210\222\344\271\213\350\277\236\347\273\255/53\346\234\200\345\244\247\350\277\236\347\273\255\345\255\220\345\272\217\345\222\214" deleted file mode 100644 index e7ae340..0000000 --- "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\212\250\346\200\201\350\247\204\345\210\222\344\271\213\350\277\236\347\273\255/53\346\234\200\345\244\247\350\277\236\347\273\255\345\255\220\345\272\217\345\222\214" +++ /dev/null @@ -1,38 +0,0 @@ -# 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 -# 示例: -# 输入: [-2,1,-3,4,-1,2,1,-5,4], -# 输出: 6 -# 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 -# def maxSubArray(self, nums: List[int]) -> int: - - -# 思路:这道是一道典型的动态规划的题目, 原因是这道题目有最优子结构, 只要求出各个部分的最优情况 -# 结果必然出现在其中, 但是不一定是出现在表中的最后一项, 这里恰好是这种情况 -# 针对以下这个例子进行讲解 -# [8, -4, 2] 从左往右看, 使用储存表dp, 注意这里dp的含义是重点: -# dp[n]的含义是站在索引为n的这个点上看, 所能选择的最大连续子序和 -# 对于第一个数来说必然只能选自己, 对于第二个数来说, 理论上存在三种可能 -# 1)选前一个最大的连续子序和但是不选自己(因为觉得自己是个负影响, 即负数) -# 2)选自己(前面的dp[n-1]是负数) -# 3)选自己与dp[n-1]的和(前面和自己都是正数) -# 注意前面三种情况其实有一种是不可选的, 那就是第一种, 从案例看吧 -# 如果对于-4所在的索引1来说, 他选第一种, 所以dp[1] = 8, 这样会使索引2认为, 我可以和8组合 -# 这样构成的数十分大, 其实这是错误的, 因为8跟索引2是有间隔的, 所以其实索引2是不可能能够选择和8组合的 -# 可见第一种可能性是存在的, 但是却不是能填入dp[1]的存在, 值得庆幸的是, 他会被储存在dp[1]的前一格 -# 也就是说这个dp表其实是有完整记录下三种可能性的, 但是第一种可能性并不是存在对应的索引处, 而是储存在 -# 这个表的某一个地方中, 但不管怎么说, 第一种可能是一个已经被固定的值, 他有竞争最优结果的可能, 但是不可 -# 被联合, 而第二三种都是可以被联合的, 为什么dp表的对应索引只能储存可以被联合的内容? -# 这是因为动态规划实则是一种依靠前后关系来迭代创建最优结果的算法思想, 所以不可被联合的数据, 其实不算是 -# 动态规划中前后关系的依据, 所以我将使用动态规划的思想, 并依据第二第三种可能进行迭代更新最优结果 -# 并且在更新完成最优的dp表后遍历一次dp表找出最大值, 因为我前面提到过第一种可能不能作为前后关系的依据, 却 -# 也是正确答案的有力竞争者, 所以最后必须遍历一次找出最大值才能找到所有可能 - - -class Solution: - def maxSubArray(self, nums): - if len(nums) == 1: - return nums[0] - dp = [nums[0]] * len(nums) - for i in range(1, len(nums)): - dp[i] = max(nums[i], nums[i]+dp[i-1]) - return max(dp) diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\233\260\351\232\276:\346\234\200\344\274\230\345\255\220\347\273\223\346\236\204\345\244\215\346\235\202/174\345\234\260\344\270\213\345\237\216\346\270\270\346\210\217" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\233\260\351\232\276:\346\234\200\344\274\230\345\255\220\347\273\223\346\236\204\345\244\215\346\235\202/174\345\234\260\344\270\213\345\237\216\346\270\270\346\210\217" deleted file mode 100644 index d7fcf9e..0000000 --- "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\233\260\351\232\276:\346\234\200\344\274\230\345\255\220\347\273\223\346\236\204\345\244\215\346\235\202/174\345\234\260\344\270\213\345\237\216\346\270\270\346\210\217" +++ /dev/null @@ -1,104 +0,0 @@ -# 一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。 -# 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。 -# 有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。 -# 为了尽快到达公主,骑士决定每次只向右或向下移动一步。 -# 编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。 -# 例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。 -# -2 (K) -3 3 -# -5 -10 1 -# 10 30 -5 (P) -# 说明: -# 骑士的健康点数没有上限。 -# 任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。 -# def calculateMinimumHP(self, dungeon: List[List[int]]) -> int: - - -# 思路:该题明显最好就是用动态规划, 一般来说, 如果要求解的枚举所有合理可能的'具体情况', 应该使用回溯法 -# 如果要求的是枚举所有合理可能的数量, 或所有合理可能中的最优可能的大概情况, -# 使用动态规划能大大减少操作量, 所以我将使用动态规划来解决这个问题 -# 我把能够安全进入一个房间需要的血量记入dp表中, 比如只有一个房间, 这个房间是加血的, 那么其实我零血进入也是可以的(最后结束时+1) -# 如果我进入一个-3的房间, 那么我需要的血量是-(-3)(最后结束时+1), 所以我们只要从终点开始倒推到起点看谁需要的血量比较少就是答案 -# 这道题要求的是勇士进入房间的最低安全血量, 分析一下, 如果勇士在第一个房间损失了10生命值, 但在下一个房间获得大量生命值回复 -# 并一路都没有再掉血, 那么勇士进房间时需要多少血量才是安全的? 高于10血, 这说明了一点, 从终点开始倒数, 一个回血的房间, 如果 -# 他能回血太多, 那其实并没有什么用, 因为他靠近终点的那些房间已经扣不完这些血量了, 所以, 这个回血的房间的增益一定没有我们 -# 想象中的大, 那么我们来具体分析一下, 如果这个回血房间(当前房间的下一个房间, 或下或右)和当前房间的血量加起来, 小于零 -# 那说明我到达当前房间还需要预留一些血, 否则就会死, 如果大于零的话, 是100血还是1000血都一样, 因为我的推理是从终点倒数的, -# 所以其实我都花不完这些血, 说明只要我能以高于零血的情况进入当前房间, 就成功了, 所以可以看出, 一个回血的房间如果回血后还是小于零 -# 那么回血是完全有效的(并且我还要自己预留一点血量否则会死, 需要预留多少血量, 那就是记录值), -# 但如果大于零, 那估计就没什么区别了, 等等, 我们漏掉了一环, 如果当前房间是扣血的, 但是在下个房间补得很满 -# (这是我们讨论回血房间记录值和当前房间加起来后血量总和超过零的一个分支), 那么我们进入这个房间时也是要带有一定血量才是安全的, -# 带有多少血量才是安全的?带有当前房间掉的血量 -# 综上:如果dungeon点+下一个房间的记录值<0, 那么直接记下(dungeon点+记录值的和), 如果>0, 还要分析, 当前房间是不是<0, 如果<0, -# 当前房间的记录值应该为当前房间的值 -# 当遇到有两种走向的房间, 就要比较那种走向需要的血量更少, (负更少), 所以取两种可能的较大值 -# 击败85, 下方有把判断写成比较值的版本, 更简洁, 但是慢很多 - - -class Solution: - def calculateMinimumHP(self, dungeon): - if dungeon == []: - return 1 - self.d = len(dungeon) - self.b = len(dungeon[0]) - dp = [[0] * self.b for i in range(self.d)] - if dungeon[-1][-1] < 0: - dp[-1][-1] = dungeon[-1][-1] - else: - dp[-1][-1] = 0 - for i in range(self.b - 2, -1, -1): - total = dp[-1][i + 1] + dungeon[-1][i] - if total > 0: - if dungeon[-1][i] > 0: - dp[-1][i] = 0 - else: - dp[-1][i] = dungeon[-1][i] - else: - dp[-1][i] = total - for i in range(self.d - 2, -1, -1): - total = dp[i + 1][-1] + dungeon[i][-1] - if total < 0: - dp[i][-1] = total - else: - if dungeon[i][-1] > 0: - dp[i][-1] = 0 - else: - dp[i][-1] = dungeon[i][-1] - for i in range(self.d - 2, -1, -1): - for j in range(self.b - 2, -1, -1): - total1 = dp[i + 1][j] + dungeon[i][j] - if total1 > 0: - if dungeon[i][j] > 0: - total1 = 0 - else: - total1 = dungeon[i][j] - total2 = dp[i][j + 1] + dungeon[i][j] - if total2 > 0: - if dungeon[i][j] > 0: - total2 = 0 - else: - total2 = dungeon[i][j] - dp[i][j] = max(total1, total2) - return -dp[0][0] + 1 - - -class Solution: - def calculateMinimumHP(self, dungeon): - if dungeon == []: - return 1 - self.d = len(dungeon) - self.b = len(dungeon[0]) - dp = [[0] * self.b for i in range(self.d)] - if dungeon[-1][-1] < 0: - dp[-1][-1] = dungeon[-1][-1] - else: - dp[-1][-1] = 0 - for i in range(self.b - 2, -1, -1): - dp[-1][i] = min(dp[-1][i + 1] + dungeon[-1][i], dungeon[-1][i], 0) - for i in range(self.d - 2, -1, -1): - dp[i][-1] = min(dp[i + 1][-1] + dungeon[i][-1], dungeon[i][-1], 0) - for i in range(self.d - 2, -1, -1): - for j in range(self.b - 2, -1, -1): - total1 = min(dp[i][j + 1] + dungeon[i][j], dungeon[i][j], 0) - total2 = min(dp[i + 1][j] + dungeon[i][j], dungeon[i][j], 0) - dp[i][j] = max(total1, total2) - return -dp[0][0] + 1 diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\22270\347\210\254\346\245\274\346\242\257" "b/\345\212\250\346\200\201\350\247\204\345\210\22270\347\210\254\346\245\274\346\242\257" deleted file mode 100644 index 4553249..0000000 --- "a/\345\212\250\346\200\201\350\247\204\345\210\22270\347\210\254\346\245\274\346\242\257" +++ /dev/null @@ -1,29 +0,0 @@ -# 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 -# 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? -# 注意:给定 n 是一个正整数。 -# 示例 1: -# 输入: 2 -# 输出: 2 -# 解释: 有两种方法可以爬到楼顶。 -# 1. 1 阶 + 1 阶 -# 2. 2 阶 -# 示例 2: -# 输入: 3 -# 输出: 3 -# 解释: 有三种方法可以爬到楼顶。 -# 1. 1 阶 + 1 阶 + 1 阶 -# 2. 1 阶 + 2 阶 -# 3. 2 阶 + 1 阶 -# def climbStairs(self, n: int) -> int: - - -# 思路:爬楼梯是一道典型的动态规划题, 跟斐波那契数列的解法也很相似 -# 这里将采用自底向上的动态规划的思路进行 - - -class Solution: - def climbStairs(self, n): - dp = [0, 1, 2] - for i in range(3, n+1): - dp.append(dp[i-1] + dp[i-2]) - return dp[n] diff --git "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/39\347\273\204\345\220\210\346\200\273\345\222\214" "b/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/39\347\273\204\345\220\210\346\200\273\345\222\214" deleted file mode 100644 index 2dfb442..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/39\347\273\204\345\220\210\346\200\273\345\222\214" +++ /dev/null @@ -1,45 +0,0 @@ -# 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 -# candidates 中的数字可以无限制重复被选取。 -# 说明: -# 所有数字(包括 target)都是正整数。 -# 解集不能包含重复的组合。  -# 示例 1: -# 输入: candidates = [2,3,6,7], target = 7, -# 所求解集为: -# [ -# [7], -# [2,2,3] -# ] -# 示例 2: -# 输入: candidates = [2,3,5], target = 8, -# 所求解集为: -# [ -#   [2,2,2,2], -#   [2,3,3], -#   [3,5] -# ] -# def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: - - -# 思路:简单的回溯,由于数字可以无限被提取,回溯算法中回退的一步pop自不用说,重点在于剪枝处理 -# 详细的关于组合剪枝手法的分析可以看leetcode解题集首页的剪枝分析 -# 复杂的点在于不能有重复解,也就是‘组合’的问题,要剔除重复解用set的话也不行,因为顺序有改动, -# 解法是一个参数start,他记录了当前用的值,如果遇到了值比当前的值要小,说明已经在前面的解里,那就跳过 - - -class Solution: - def combinationSum(self, candidates, target): - self.lst = [] - self.size = len(candidates) - self.backtrack(candidates, target, 0, 0, []) - return self.lst - - def backtrack(self, candidates, target, start, total, lst): - if total == target: - self.lst.append(lst[:]) - return - for i in range(self.size): - if total + candidates[i] <= target and candidates[i] >= start: - lst.append(candidates[i]) - self.backtrack(candidates, target, candidates[i], total+candidates[i], lst) - lst.pop() diff --git "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/40\347\273\204\345\220\210\346\200\273\345\222\2142" "b/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/40\347\273\204\345\220\210\346\200\273\345\222\2142" deleted file mode 100644 index d909f96..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/40\347\273\204\345\220\210\346\200\273\345\222\2142" +++ /dev/null @@ -1,53 +0,0 @@ -# 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 -# candidates 中的每个数字在每个组合中只能使用一次。 -# 说明: -# 所有数字(包括目标数)都是正整数。 -# 解集不能包含重复的组合。  -# 示例 1: -# 输入: candidates = [10,1,2,7,6,1,5], target = 8, -# 所求解集为: -# [ -# [1, 7], -# [1, 2, 5], -# [2, 6], -# [1, 1, 6] -# ] -# 示例 2: -# 输入: candidates = [2,5,2,1,2], target = 5, -# 所求解集为: -# [ -#   [1,2,2], -#   [5] -# ] -# def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]: - - -# 思路:这种比39题的更复杂一点,因为他有重复元素,但是没关系, -# 对于没有复用元素的基础的回溯算法一定是通过visited表来表示已用 -# 中等难度的回溯,由于存在重复元素所以要在基础的非复用情况下的回溯算法基础上增加一个剪枝判断, -# 在for循环的内容增加一个判断,如果同层循环中获取的这个数不比上一个数就否决这种可能 -# 详细的关于组合剪枝手法的分析可以看leetcode解题集首页的剪枝分析 - - -class Solution: - def combinationSum2(self, candidates, target): - self.lst = [] - self.size = len(candidates) - candidates.sort() - # self.visited = [False] * self.size - self.backtrack(candidates, target, 0, 0, []) - return self.lst - - - def backtrack(self, candidates, target, record, total, lst): - if total == target: - self.lst.append(lst[:]) - return - last = 0 - for i in range(record, self.size): - if candidates[i] + total <= target and last < candidates[i]: - last = candidates[i] - lst.append(candidates[i]) - self.backtrack(candidates, target, i+1, total + candidates[i], lst) - lst.pop() - return diff --git "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/46\345\205\250\346\216\222\345\210\227" "b/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/46\345\205\250\346\216\222\345\210\227" deleted file mode 100644 index b3808da..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/46\345\205\250\346\216\222\345\210\227" +++ /dev/null @@ -1,42 +0,0 @@ -# 给定一个没有重复数字的序列,返回其所有可能的全排列。 -# 示例: -# 输入: [1,2,3] -# 输出: -# [ -# [1,2,3], -# [1,3,2], -# [2,1,3], -# [2,3,1], -# [3,1,2], -# [3,2,1] -# ] -# def permute(self, nums: List[int]) -> List[List[int]]: - - -# 思路:典型的回溯法中, 全排列无需剪枝的情况, 由于元素不可复用, 附加一个检查表 -# 由于元素的值之间没有关联性, 所以我采用字典作为检查表容器(不一定要用字典) - - -class Solution: - def permute(self, nums): - if nums == []: - return [] - self.res = [] - self.visited = {} - for i in nums: - self.visited[i] = True - self.dfs(nums, 0, []) - return self.res - - def dfs(self, nums, index, lst): - if index == len(nums): - self.res.append(lst[:]) - return - for i in self.visited: - if self.visited[i]: - lst.append(i) - self.visited[i] = False - self.dfs(nums, index+1, lst) - lst.pop() - self.visited[i] = True - return diff --git "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/47\344\270\215\351\207\215\345\244\215\347\232\204\345\205\250\346\216\222\345\210\227" "b/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/47\344\270\215\351\207\215\345\244\215\347\232\204\345\205\250\346\216\222\345\210\227" deleted file mode 100644 index 0286a8c..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/47\344\270\215\351\207\215\345\244\215\347\232\204\345\205\250\346\216\222\345\210\227" +++ /dev/null @@ -1,79 +0,0 @@ -# 给定一个可包含重复数字的序列,返回所有不重复的全排列。 -# 示例: -# 输入: [1,1,2] -# 输出: -# [ -# [1,1,2], -# [1,2,1], -# [2,1,1] -# ] -# def permuteUnique(self, nums: List[int]) -> List[List[int]]: - - -# 思路:典型的回溯法中, 由于元素不可复用, 且存在重复元素 -# 所以解法是基础回溯算法(使用一个检查表或者使用哈希) -# 且这里的例子说明112和211不算重复(即相同的元素出现并不算重复) -# 只需要用检查表即可, 不需要用到收缩列表的方法 -# (因为收缩列表是带了剪枝功能的, 但是211在本题不算枝节) -# 由于元素的值之间没有关联性, 所以采用字典作为检查表容器 -# 存在剪枝情况, 关于如何剪枝, 在我的leetcode解题集的首页有一个关于回溯法中有关剪枝 -# 的具体情况分析和应对策略的总结, 这里将采用排序后在for循环内部否决的方式来剪枝 - - -class Solution: - def permuteUnique(self, nums): - if nums == []: - return [] - self.res = [] - nums.sort() - self.visited = {} - for i in nums: - if i not in self.visited: - self.visited[i] = 1 - else: - self.visited[i] += 1 - self.dfs(nums, 0, []) - return self.res - - def dfs(self, nums, index, lst): - if index == len(nums): - self.res.append(lst[:]) - return - rec = nums[0]-1 - for i in self.visited: - if self.visited[i] > 0 and i > rec: # 这里的i > rec就是循环内部剪枝 - lst.append(i) - self.visited[i] -= 1 - self.dfs(nums, index+1, lst) - lst.pop() - self.visited[i] += 1 - rec = i - return - - -# 直接在一个数组上进行记录(不使用字典), 这个数组上的索引对应着排序后的数组的索引 -class Solution: - def permuteUnique(self, nums): - if nums == []: - return [] - self.res = [] - nums.sort() - self.size = len(nums) - self.visited = [True] * self.size - self.dfs(nums, 0, []) - return self.res - - def dfs(self, nums, index, lst): - if index == self.size: - self.res.append(lst[:]) - return - rec = nums[0] - 1 - for i in range(self.size): - if self.visited[i] and i > rec:# 这里的nums[i] > rec就是循环内部剪枝 - lst.append(nums[i]) - self.visited[i] = False - self.dfs(nums, index + 1, lst) - lst.pop() - self.visited[i] = True - rec = nums[i] - return diff --git "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/77\347\273\204\345\220\210" "b/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/77\347\273\204\345\220\210" deleted file mode 100644 index 4a83014..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/77\347\273\204\345\220\210" +++ /dev/null @@ -1,37 +0,0 @@ -# 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。 -# 示例: -# 输入: n = 4, k = 2 -# 输出: -# [ -# [2,4], -# [3,4], -# [2,3], -# [1,2], -# [1,3], -# [1,4], -# ] -# def combine(self, n: int, k: int) -> List[List[int]]: - - -# 思路:回溯, 经典的基础回溯算法(组合, 不可重用, 没有重复元素) -# 我将使用缩小可选范围来剪枝(125 和512, 在首位是5的时候, 是不存在1和2可选的) -# 由于只能在index到达指定位置时才收集答案, 所以无论是缩小可选范围还是 -# 制visit表都需要增加递归终止条件 - - -class Solution: - def combine(self, n, k): - self.lst = [] - self.bt(n, k, 0, 1, []) - return self.lst - - def bt(self, n, k, index, lstindex, lst): - if index >= k: - self.lst.append(lst[:]) - return - for i in range(lstindex, n+1): - if n+1-i >= k-index: - lst.append(i) - self.bt(n, k, index+1, i+1, lst) - lst.pop() - return diff --git "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/78\345\255\220\351\233\206\351\233\206\345\220\210" "b/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/78\345\255\220\351\233\206\351\233\206\345\220\210" deleted file mode 100644 index 654e55e..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/78\345\255\220\351\233\206\351\233\206\345\220\210" +++ /dev/null @@ -1,36 +0,0 @@ -# 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 -# 说明:解集不能包含重复的子集。 -# 示例: -# 输入: nums = [1,2,3] -# 输出: -# [ -# [3], -#   [1], -#   [2], -#   [1,2,3], -#   [1,3], -#   [2,3], -#   [1,2], -#   [] -# ] -# def subsets(self, nums: List[int]) -> List[List[int]]: - - -# 思路:不重用,无重复元素,不包含重复子集, 即组合需要剪枝 -# 使用基础回溯算法(可以用visit表或者直接收缩可选范围可达到剪枝效果) - - -class Solution: - def subsets(self, nums): - self.size = len(nums) - self.res = [[]] - self.backtrack(nums, 0, []) - return self.res - - def backtrack(self, nums, index, lst): - for i in range(index, self.size): - lst.append(nums[i]) - self.res.append(lst[:]) - self.backtrack(nums, i+1, lst) - lst.pop() - return diff --git "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/90\345\255\220\351\233\206II" "b/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/90\345\255\220\351\233\206II" deleted file mode 100644 index 76ec4f1..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\346\225\260\347\273\204\347\232\204\346\216\222\345\210\227\344\270\216\347\273\204\345\220\210/90\345\255\220\351\233\206II" +++ /dev/null @@ -1,41 +0,0 @@ -# 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 -# 说明:解集不能包含重复的子集。 -# 示例: -# 输入: [1,2,2] -# 输出: -# [ -# [2], -# [1], -# [1,2,2], -# [2,2], -# [1,2], -# [] -# ] -# def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: - - -# 思路:详细分析看我的leetcode库首页中关于组合的剪枝分析 -# 此处由于包含重复元素, 所以要先排序, 并增加一个循环内部判断变量, -# 由于不能包含重复子集, 所以是组合, 用基础的回溯算法visit表或收缩范围 -# 使用收缩范围的方法等于自带递归终止条件对于收集子集的题目来说 -# (因为不需要到达对应index才能收集答案) - - -class Solution: - def subsetsWithDup(self, nums): - self.res = [[]] - self.size = len(nums) - nums.sort() - self.backtrack(nums, 0, []) - return self.res - - def backtrack(self, nums, index, lst): - total = 0 - for i in range(index, self.size): - if total < nums[i]: - total = nums[i] - lst.append(nums[i]) - self.res.append(lst[:]) - self.backtrack(nums, i+1, lst) - lst.pop() - return diff --git "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/17\347\224\265\350\257\235\345\217\267\347\240\201\347\273\204\345\220\210" "b/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/17\347\224\265\350\257\235\345\217\267\347\240\201\347\273\204\345\220\210" deleted file mode 100644 index aa17a7b..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/17\347\224\265\350\257\235\345\217\267\347\240\201\347\273\204\345\220\210" +++ /dev/null @@ -1,33 +0,0 @@ -# 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 -# 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 -# 示例: -# 输入:"23" -# 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. -# 说明: -# 尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。 -# def letterCombinations(self, digits: str) -> List[str]: - - -# 思路:这个题目的要求是得到所有合理可能性的所有组合的具体情况, 所以用的方法是回溯法 -# 并且这里的题意表示这里没有互斥关系, 所以这里的所有组合的可能性都是合理可能性, 不需要剪枝 - - -class Solution: - def letterCombinations(self, digits): - if digits == '': - return [] - self.res = [] - self.dct = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'} - self.dfs(digits, 0, []) - return self.res - - def dfs(self, digits, index, lst): - if index == len(digits): - res = ''.join(lst) - self.res.append(res) - return - for i in self.dct[digits[index]]: - lst.append(i) - self.dfs(digits, index+1, lst) - lst.pop() - return diff --git "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/22\346\213\254\345\217\267\347\224\237\346\210\220" "b/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/22\346\213\254\345\217\267\347\224\237\346\210\220" deleted file mode 100644 index d826f92..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/22\346\213\254\345\217\267\347\224\237\346\210\220" +++ /dev/null @@ -1,41 +0,0 @@ -# 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。 -# 例如,给出 n = 3,生成结果为: -# [ -# "((()))", -# "(()())", -# "(())()", -# "()(())", -# "()()()" -# ] -# def generateParenthesis(self, n: int) -> List[str]: - - -# 思路:回溯并且判断出不合理(括号无效)的可能否决掉,合理的可能放入列表 - - -class Solution: - def generateParenthesis(self, n): - self.visited = {-1:n, 1:n} - self.dct = {-1:')', 1:'('} - self.res = [] - self.dfs(2*n, 0, 0, []) - return self.res - - - def dfs(self, n, index, total, lst): - # 这里的n就是上面的2*n, 减少计算 - if total < 0: - return - if index == n and total == 0: - lst = [self.dct[i] for i in lst] - print(lst) - res = ''.join(lst) - self.res.append(res) - for i in self.visited: - if self.visited[i] > 0: - self.visited[i] -= 1 - lst.append(i) - self.dfs(n, index+1, total+i, lst) - lst.pop() - self.visited[i] += 1 - return diff --git "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/51N\347\232\207\345\220\216" "b/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/51N\347\232\207\345\220\216" deleted file mode 100644 index 902bfec..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/51N\347\232\207\345\220\216" +++ /dev/null @@ -1,67 +0,0 @@ -# n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 -# 上图为 8 皇后问题的一种解法。 -# 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。 -# 每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。 -# 示例: -# 输入: 4 -# 输出: [ -# [".Q..", // 解法 1 -# "...Q", -# "Q...", -# "..Q."], -# ["..Q.", // 解法 2 -# "Q...", -# "...Q", -# ".Q.."] -# ] -# 解释: 4 皇后问题存在两个不同的解法。 -# def solveNQueens(self, n: int) -> List[List[str]]: - - -# 思路:这是一道很经典的回溯题, 更仔细的分析会发现, 这道回溯题是属于排列类的, -# 跟数组类排列与组合类的回溯题略有不同, 主要在于排列与组合类型的回溯重在思考 -# 剪枝过程, 并且由于基本上都跟数组有关, 所以很多时候他们的占位是可以用数值本身 -# 的大小关系来判断的, 也就是说可以不需要一个实际的判断表也可以做到回溯。 -# 但是像8皇后这种经典的排列类回溯题, 他们的难点主要集中在判断占位的表的设定, -# 一旦判断占位的表的设定想好了, 判断方案也就水到渠成了, 这种排除不合理答案的 -# 过程本身就是剪枝, 所以从这个角度来看, 像8皇后这类的回溯题, 跟数组上进行排列 -# 组合的回溯题略有不同 -# 这道8皇后的回溯题很明显在于判断占位表的设定, 在没有解决过这类涉及一个点的 -# 多重判断的时候, 很可能是解答不了的, 因为很难想像出怎么样可以设计出一个好的 -# 判断方案, 这里使用的是一列和两对角线的占位表辅助判断 -# 其实我一开始是想用xy坐标来做占位表的, 不过发现对待斜向判断会很难写, 所以 -# 参考标准8皇后解法, 用一列两对角线的占位表来辅助判断 - - -class Solution: - def solveNQueens(self, n): - if n == 0: - return [] - self.res = [] - self.col = [True] * n - self.dia1 = [True] * (2*n-1) - self.dia2 = [True] * (2*n-1) - self.dfs(n, 0, []) - return self.res - - def dfs(self, n, index, lst): - if index == n: - self.res.append(self.helper(n, lst)) - return - for i in range(n): - if self.col[i] and self.dia1[index+i] and self.dia2[index-i+n-1]: - self.col[i] = False - self.dia1[index + i] = False - self.dia2[index - i + n - 1] = False - lst.append(i) - self.dfs(n, index+1, lst) - self.col[i] = True - self.dia1[index + i] = True - self.dia2[index - i + n - 1] = True - lst.pop() - - def helper(self, n, lst): - res = [['.' for i in range(n)] for j in range(n) ] - for i in range(n): - res[i][lst[i]] = 'Q' - return [''.join(i) for i in res] diff --git "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/52N\347\232\207\345\220\2162\346\261\202\350\247\243\346\225\260\351\207\217" "b/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/52N\347\232\207\345\220\2162\346\261\202\350\247\243\346\225\260\351\207\217" deleted file mode 100644 index 40b2cc5..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/52N\347\232\207\345\220\2162\346\261\202\350\247\243\346\225\260\351\207\217" +++ /dev/null @@ -1,51 +0,0 @@ -# n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 -# 上图为 8 皇后问题的一种解法。 -# 给定一个整数 n,返回 n 皇后不同的解决方案的数量。 -# 示例: -# 输入: 4 -# 输出: 2 -# 解释: 4 皇后问题存在如下两个不同的解法。 -# [ -#  [".Q..",  // 解法 1 -#   "...Q", -#   "Q...", -#   "..Q."], -# -#  ["..Q.",  // 解法 2 -#   "Q...", -#   "...Q", -#   ".Q.."] -# ] -# def totalNQueens(self, n: int) -> int: - - -# 思路:详细分析可以看51题N皇后, 这道题在完成了N皇后基本上只需要把收集 -# 具体情况的操作换成计数, 就是这道题的解 - - -class Solution: - def totalNQueens(self, n: int) -> int: - if n == 0: - return [] - self.res = 0 - self.col = [True] * n - self.dia1 = [True] * (2*n-1) - self.dia2 = [True] * (2*n-1) - self.dfs(n, 0, []) - return self.res - - def dfs(self, n, index, lst): - if index == n: - self.res += 1 - return - for i in range(n): - if self.col[i] and self.dia1[index+i] and self.dia2[index-i+n-1]: - self.col[i] = False - self.dia1[index + i] = False - self.dia2[index - i + n - 1] = False - lst.append(i) - self.dfs(n, index+1, lst) - self.col[i] = True - self.dia1[index + i] = True - self.dia2[index - i + n - 1] = True - lst.pop() diff --git "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/79\344\272\214\347\273\264\346\225\260\347\273\204\344\270\255\346\211\276\345\215\225\350\257\215" "b/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/79\344\272\214\347\273\264\346\225\260\347\273\204\344\270\255\346\211\276\345\215\225\350\257\215" deleted file mode 100644 index fe25204..0000000 --- "a/\345\233\236\346\272\257\346\263\225/\351\235\236\346\225\260\345\200\274\347\261\273\346\216\222\345\210\227/79\344\272\214\347\273\264\346\225\260\347\273\204\344\270\255\346\211\276\345\215\225\350\257\215" +++ /dev/null @@ -1,76 +0,0 @@ -# 给定一个二维网格和一个单词,找出该单词是否存在于网格中。 -# 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 -# 示例: -# board = -# [ -# ['A','B','C','E'], -# ['S','F','C','S'], -# ['A','D','E','E'] -# ] -# 给定 word = "ABCCED", 返回 true. -# 给定 word = "SEE", 返回 true. -# 给定 word = "ABCB", 返回 false. -# def exist(self, board: List[List[str]], word: str) -> bool: - - -# 思路:这是典型的基于图类型的回溯法, 在回溯法的剪枝策略分析的时候有提到过 -# 对着这种非数组类的排列问题, 要用到判断表, 然后针对四个方向的可能都进行回溯尝试 -# 如果所有尝试都没找到答案, 则False, 如果找到有答案, 则True -# 由于给定的是单词, 所以一定有首位字母, 对于与首位字母不符的字母, 不需要进行 -# 深度优先搜索/回溯, 直接跳过 - - -class Solution: - def exist(self, board, word): - self.size = len(word) - if self.size < 1: - return None - lst = [] - self.d = len(board) - self.b = len(board[0]) - self.total = [] - for i in range(self.d): - self.total.append([True] * self.b) - for i in range(self.d): - for n in range(self.b): - if board[i][n] == word[0]: - lst.append([i, n]) - if lst == []: - return False - self.res = None - for i in lst: - if len(word) == 1: - return True - self.backtrack(i, 0, board, word) - if self.res: - return True - return False - - def backtrack(self, start, index, board, word): - if index == self.size: - self.res = True - return True - if board[start[0]][start[1]] == word[index] and self.total[start[0]][start[1]]: - self.total[start[0]][start[1]] = False - if 0 < start[0]: - start[0] -= 1 - if self.backtrack(start, index + 1, board, word): - return True - start[0] += 1 - if self.d - 1 > start[0]: - start[0] += 1 - if self.backtrack(start, index + 1, board, word): - return True - start[0] -= 1 - if 0 < start[1]: - start[1] -= 1 - if self.backtrack(start, index + 1, board, word): - return True - start[1] += 1 - if self.b - 1 > start[1]: - start[1] += 1 - if self.backtrack(start, index + 1, board, word): - return True - start[1] -= 1 - self.total[start[0]][start[1]] = True - return False diff --git "a/\346\240\210/103\346\240\221\347\232\204\351\224\257\351\275\277\347\212\266\345\261\202\345\272\217\351\201\215\345\216\206" "b/\346\240\210/103\346\240\221\347\232\204\351\224\257\351\275\277\347\212\266\345\261\202\345\272\217\351\201\215\345\216\206" deleted file mode 100644 index 5847e6e..0000000 --- "a/\346\240\210/103\346\240\221\347\232\204\351\224\257\351\275\277\347\212\266\345\261\202\345\272\217\351\201\215\345\216\206" +++ /dev/null @@ -1,58 +0,0 @@ -# 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 -# -# 例如: -# 给定二叉树 [3,9,20,null,null,15,7], -# -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# 返回锯齿形层次遍历如下: -# -# [ -# [3], -# [20,9], -# [15,7] -# ] -# def levelOrder(self, root: TreeNode) -> List[List[int]]: - - -# 思路:此处应该使用栈 -# 参考102树的层序遍历的思路, 103需要在这个基础上改为使用栈结构 -# 在每次获取节点时, 放入栈中, 并且每次获取节点的时候如果节点是属于新层的 -# 那么改变节点的左右子节点的存入顺序 -# 使用两个栈, 一个栈负责上一层, 一个栈负责下一层 -# 当上层的栈为空时, 下层的节点必然已经全部存入下层栈, -# 把下层栈变为上层栈, 生成新的下层栈, 循环进行 -# 直至下层栈的内容为空, 则说明遍历完成 -from queue import LifoQueue - - -class Solution: - def levelOrder(self, root): - if not root: - return [] - q = LifoQueue() - lst = [] - q.put((root, 0)) - while not q.empty(): - q2 = LifoQueue() - while not q.empty(): - cur, level = q.get() - if level > len(lst) - 1: - llst = [] - lst.append(llst) - llst.append(cur.val) - if level % 2: - if cur.right: - q2.put((cur.right, level + 1)) - if cur.left: - q2.put((cur.left, level + 1)) - else: - if cur.left: - q2.put((cur.left, level + 1)) - if cur.right: - q2.put((cur.right, level + 1)) - q = q2 - return lst diff --git "a/\346\240\210/144\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206" "b/\346\240\210/144\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206" deleted file mode 100644 index 1056911..0000000 --- "a/\346\240\210/144\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206" +++ /dev/null @@ -1,38 +0,0 @@ -# 给定一个二叉树,返回它的 前序 遍历。 -#  示例: -# 输入: [1,null,2,3] -# 1 -# \ -# 2 -# / -# 3 -# 输出: [1,2,3] -# def preorderTraversal(self, root: TreeNode) -> List[int]: - - -# 思路:二叉树的前序遍历的非递归写法是典型的使用栈的例子, 核心原因是偏深度型的遍历 -# (不会在获取了一个二叉树的左节点后直接获取同级右节点, 而是要先获取左子树的左子树) -# 这决定了在遍历了一个树的左子树后必须依靠返回父节点的方式去遍历右子树, 要从子节点 -# 返回父节点, 是典型的后进先出结构, 使用栈 -# 对于前序遍历来说, 由于使用栈这种后进先出结构能够让我们遍历了一个树的左子树后能够 -# 返回到父节点进而遍历右子树, 这里反而形成一个思维误区, 以为压入栈的顺序是父左右 -# 其实对于栈来说, 如果想先出栈的子树是左子树的话, 反而应该先压入右子树 -from queue import LifoQueue - - -class Solution: - def preorderTraversal(self, root): - if root == None: - return - cur = root - q = LifoQueue() - lst = [] - q.put(cur) - while not q.empty(): - cur = q.get() - lst.append(cur.val) - if cur.right != None: - q.put(cur.right) - if cur.left != None: - q.put(cur.left) - return lst diff --git "a/\346\240\210/145\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206" "b/\346\240\210/145\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206" deleted file mode 100644 index 8218a73..0000000 --- "a/\346\240\210/145\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206" +++ /dev/null @@ -1,91 +0,0 @@ -# 给定一个二叉树,返回它的 后序 遍历。 -# 示例: -# 输入: [1,null,2,3] -# 1 -# \ -# 2 -# / -# 3 -# 输出: [3,2,1] -# 进阶: 递归算法很简单,你可以通过迭代算法完成吗? -# def postorderTraversal(self, root: TreeNode) -> List[int]: - - -# 思路:二叉树的后序遍历的非递归写法是典型的使用栈的例子, 并且比前中序遍历的写法 -# 更要复杂一丢丢 -# 这里将会使用两个栈来完成后续遍历, 由于后序遍历的顺序是左右本身 -# 所以将会按 本身->右->左 的节点顺序压入栈2 -# 所以栈1的顺序应该是先压入根节点, 取出, 取出这个节点后要压入当前节点的左右节点 -# 因为是后进先出的结构, 所以取出的时候会先取出当前节点的右节点再取出左节点 -# 正符合前面对于栈2压入顺序的构思 -# 另外附上自创的更为复杂和麻烦的后序遍历写法 -from queue import LifoQueue - - -class Solution: - def postorderTraversal(self, root): - p = LifoQueue() - q = LifoQueue() - p.put(root) - lst = [] - while not p.empty(): - # 由于压入栈1的顺序是先右后左, 所以他先把根节点压入栈2后会先深度遍历 - # 右子树, 再深度遍历左子树(如果画图的话可以看出这跟递归的感觉很相似) - root = p.get() - q.put(root) - if root.left: - p.put(root.left) - if root.right: - p.put(root.right) - while not q.empty(): - root = q.get() - lst.append(root.val) - return lst - - -# 先根据二叉树的后序遍历的思路来分析:我们要偏深度优先型的遍历一棵树的左子树右子树 -# 最后才到自身, 由于前面分析前中序遍历时分析过, 对于非广度优先的这种遍历方式限制了 -# 我们不能在获取了一个树的左子树后立刻访问他的右子树, 这导致我们必然要在遍历了一个 -# 树的左子树后先把该树存起来, 提供给后续访问右子树之用, 由于遍历完一个树的左子树后 -# 要返回到这个树本身的节点, 这导致我们只能使用栈这种结构, 并且在后序遍历时我们会 -# 遇到一个问题:我们在遍历完一个树的左子树后还不能遍历这个树本身, 而是要先遍历完这个 -# 树的右子树, 却要在最后再遍历自身, 这说明这个树曾经拿出来, 但是又放回去了 -# 所以重点就是把树放回去的时机和再次拿出来的时机的判断 -# 如果不能做到在一个节点被第二次从栈中取出时判断出该树已经遍历完的话将会陷入死循环, -# 所以还要加入一个判断 - - -class Solution: - def postorderTraversal(self, root): - if root == None: - return - q = LifoQueue() - lst = [] - cur = root - q.put(cur) - while cur.left != None:# 由浅入深存如一个个树的自身, 直至树的最左端 - cur = cur.left - q.put(cur) - lst2 = [0] - while True: - cur = q.get() - if cur.right != None:# 如果当前树存在右子树, 且没有被记录过, 只能先把当前树又压回栈了 - if cur != lst2[-1]: - q.put(cur) - lst2.append(cur) - cur = cur.right - - q.put(cur) - while cur.left != None: - cur = cur.left - q.put(cur) - else: - lst2.pop() - lst.append(cur.val) - if cur == root: - break - else: - lst.append(cur.val) - if cur == root: - break - return lst diff --git "a/\346\240\210/150\351\200\206\346\263\242\345\205\260\350\241\250\350\276\276\345\274\217" "b/\346\240\210/150\351\200\206\346\263\242\345\205\260\350\241\250\350\276\276\345\274\217" deleted file mode 100644 index d81fe32..0000000 --- "a/\346\240\210/150\351\200\206\346\263\242\345\205\260\350\241\250\350\276\276\345\274\217" +++ /dev/null @@ -1,31 +0,0 @@ -# 根据逆波兰表示法,求表达式的值。 -# 有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 -# 说明: -# 整数除法只保留整数部分。 -# 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 -# 示例 1: -# 输入: ["2", "1", "+", "3", "*"] -# 输出: 9 -# 解释: ((2 + 1) * 3) = -# def evalRPN(self, tokens: List[str]) -> int: - - -# 思路:用的是先出现数字再出现符号的表达方式, 为了得到正常通用的中序表达式 -# 我们采用后进先出结构, 当我们遇到符号时, 说明前一个数字应该出现在这个符号的后方 -# 做成中序表达式让计算机求值 -from queue import LifoQueue - - -class Solution: - def evalRPN(self, tokens): - lst = ['+', '-', '*', '/'] - q = LifoQueue() - for i in tokens: - if i not in lst: - q.put(i) - else: - total = '' + q.get() - total = total + i - total = total + q.get() - q.put(str(eval(total))) - return int(q.get()) diff --git "a/\346\240\210/155\346\234\200\345\260\217\346\240\210" "b/\346\240\210/155\346\234\200\345\260\217\346\240\210" deleted file mode 100644 index c86b461..0000000 --- "a/\346\240\210/155\346\234\200\345\260\217\346\240\210" +++ /dev/null @@ -1,43 +0,0 @@ -# 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。 -# push(x) -- 将元素 x 推入栈中。 -# pop() -- 删除栈顶的元素。 -# top() -- 获取栈顶元素。 -# getMin() -- 检索栈中的最小元素。 -# 示例: -# MinStack minStack = new MinStack(); -# minStack.push(-2); -# minStack.push(0); -# minStack.push(-3); -# minStack.getMin(); --> 返回 -3. -# minStack.pop(); -# minStack.top(); --> 返回 0. -# minStack.getMin(); --> 返回 -2. - - -# 思路:基本要求是设计一个栈, 但是增加一个要求能够常数级显示栈中的最小元素, -# 所以必须要多用一个栈来压入当前情况的最小值, 如果新压入的值比原有最小值更小 -# 那就把这个值也压入辅助栈中, 唯一需要注意的是如果辅助栈是空的, 别忘了强制加入当前压入值(不需判断) -class MinStack: - - def __init__(self): - self.data = [] # 数据栈 - self.helper = [] # 辅助栈 - - def push(self, val): - self.data.append(val) - if len(self.helper) == 0 or val <= self.helper[-1]: - self.helper.append(val) - - def pop(self): - res = self.data.pop() - if self.helper and res == self.helper[-1]: - self.helper.pop() - return res - - def top(self): - if self.data: - return self.data[-1] - - def getMin(self): - if self.helper: - return self.helper[-1] diff --git "a/\346\240\210/20\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267" "b/\346\240\210/20\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267" deleted file mode 100644 index 944b5c4..0000000 --- "a/\346\240\210/20\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267" +++ /dev/null @@ -1,41 +0,0 @@ -# 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 -# 有效字符串需满足: -# 左括号必须用相同类型的右括号闭合。 -# 左括号必须以正确的顺序闭合。 -# 注意空字符串可被认为是有效字符串。 -# 示例 1: -# 输入: "()" -# 输出: true -# 示例 2: -# 输入: "()[]{}" -# 输出: true -# 示例 3: -# 输入: "(]" -# 输出: false -# 示例 4: -# 输入: "([)]" -# 输出: false -# 示例 5: -# 输入: "{[]}" -# 输出: true -# def isValid(self, s: str) -> bool: - - -# 思路:判断三种括号是否的正确性明显用到了栈的功能,因为括号的正确使用情况是里面的和里面作用,外面的和外面的一起作用 -# [()]这一点恰恰用到了栈后进先出的特性 -from queue import LifoQueue - - -class Solution: - def isValid(self, s): - dct = {')': '(', ']': '[', '}': '{'} - q = LifoQueue() - for i in s: - if i not in dct: - q.put(i) - else: - if q.empty() or q.get() != dct[i]: - return False - if q.empty(): - return True - return False diff --git "a/\346\240\210/32\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267" "b/\346\240\210/32\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267" deleted file mode 100644 index b5e34d7..0000000 --- "a/\346\240\210/32\346\234\200\351\225\277\346\234\211\346\225\210\346\213\254\345\217\267" +++ /dev/null @@ -1,38 +0,0 @@ -# 给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。 -# 示例 1: -# 输入: "(()" -# 输出: 2 -# 解释: 最长有效括号子串为 "()" -# 示例 2: -# 输入: ")()())" -# 输出: 4 -# 解释: 最长有效括号子串为 "()()" -# def longestValidParentheses(self, s: str) -> int: - - -# 思路:利用栈来判断括号是否有效, 并且进行计数 -# 由于存在类似'()(()'这种情况, 如果在最后结算一次把前面两个加进结果, -# 那结果是错误的, -# 不结算最后一段有效的括号的话也是不正确的, -# 所以决定存入对应的索引, 而不是存入'(' -# 最后通过索引来加以判断 -from queue import LifoQueue - - -class Solution: - def longestValidParentheses(self, s): - q = LifoQueue() - q.put(-1) - res = 0 # 结果值 - for i in range(len(s)): - if s[i] == '(': - q.put(i) - else: - q.get() - if q.empty(): - q.put(i) - else: - total = q.get() - q.put(total) - res = max(res, i-total) - return res diff --git "a/\346\240\210/71\347\256\200\345\214\226\350\267\257\345\276\204" "b/\346\240\210/71\347\256\200\345\214\226\350\267\257\345\276\204" deleted file mode 100644 index edd9d56..0000000 --- "a/\346\240\210/71\347\256\200\345\214\226\350\267\257\345\276\204" +++ /dev/null @@ -1,42 +0,0 @@ -# 以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。 -# 在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径 -# 请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。 -# 示例 1: -# 输入:"/home/" -# 输出:"/home" -# 解释:注意,最后一个目录名后面没有斜杠。 -# 示例 2: -# 输入:"/../" -# 输出:"/" -# 解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。 -# 示例 3: -# 输入:"/home//foo/" -# 输出:"/home/foo" -# 解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。 -# 示例 4: -# 输入:"/a/./b/../../c/" -# 输出:"/c" -# 示例 5: -# 输入:"/a/../../b/../c//.//" -# 输出:"/c" -# 示例 6: -# 输入:"/a//b////c/d//././/.." -# 输出:"/a/b/c" -# def simplifyPath(self, path: str) -> str: - - -# 思路:这个一个系统中用栈的典型情况,后退获取后进先出,遇到'..'代表返回上一层用到了后进先出 - - -class Solution: - def simplifyPath(self, path): - # 把字符串用/进行分割 - lst = path.split('/') - llst = [] - for i in lst: - if i == '..' and len(llst) > 0: - llst.pop() - elif i != '' and i != '.' and i != '..': - llst.append(i) - print(llst) - return '/' + '/'.join(llst) diff --git "a/\346\240\210/94\344\270\255\345\272\217\351\201\215\345\216\206\344\272\214\345\217\211\346\240\221" "b/\346\240\210/94\344\270\255\345\272\217\351\201\215\345\216\206\344\272\214\345\217\211\346\240\221" deleted file mode 100644 index 3b5784a..0000000 --- "a/\346\240\210/94\344\270\255\345\272\217\351\201\215\345\216\206\344\272\214\345\217\211\346\240\221" +++ /dev/null @@ -1,76 +0,0 @@ -# 给定一个二叉树,返回它的中序 遍历。 -# 示例: -# 输入: [1,null,2,3] -# 1 -# \ -# 2 -# / -# 3 -# 输出: [1,3,2] -# 进阶: 递归算法很简单,你可以通过迭代算法完成吗? -# def inorderTraversal(self, root: TreeNode) -> List[int]: - - -# 思路:从根节点开始, 向左子树走, 把路过的所有节点都压入栈(包括空) -# 直到为空, 说明到达了当前树的最左端, 由于是中序遍历, 这时候可以回一步 -# 变成空之前的那个节点, 把节点值记录下来, 把右子树压入栈中(包括空) -# 如果右子树为空就会回一步, 如果不为空就会把刚才的步骤再进行一次 -# 这和递归的思路很相似, 基本就是递归思路的改写, 非常巧妙, 附上分析 -# 另外附上我自创的利用栈的特性来进行的中序遍历(当然比起标准的思路要复杂和麻烦不少) -from queue import LifoQueue - - -class Solution: - def inorderTraversal(self, root): - if root == None: - return None - p = LifoQueue() - lst = [] - while root != None or not p.empty(): - # if root == None: - # return None - # self.inorder(self, root.left) - # lst.append(root.val) - # self.inorder(self, root.right) - if root != None: - # 当root不为空的时候, 传入左节点递归, 直到为空, 对应32行 - p.put(root) - root = root.left - else: - # 当root为空的时候(32行), 返回上一层节点, 并且记录值, 递归该节点的右节点, 对应33,34行 - root = p.get() - lst.append(root.val) - root = root.right - return lst - - -# 二叉树的前中后序遍历的非递归写法是一个典型的使用栈的例子(因为他们都需要在 -# 遍历一个子节点后回到父节点或者通过父节点的帮助去遍历另一个子节点), 这恰恰用到了 -# 栈的后进先出特性来返回父节点, 对于中序遍历来说,做法主要是先从根节点开始把根节点压入栈 -# 然后把左节点压入栈, 直至树的最左端, 然后可以开始获取节点(此时此节点就是一棵二叉树 -# 中最左端的二叉树), 所以在读取了自己的值后, 开始判断右子树是否为空, 不为空则进入右 -# 子树开始下一次前序遍历, 直到读取了值的树的右子树为空的时候, 那棵树算遍历完成了, -# 继续从栈中出去那棵树的父节点, 直至最后取出根节点 - - -class Solution: - def inorderTraversal(self, root): - if root == None: - return - cur = root - lst = [] - q = LifoQueue() - q.put(cur) - while cur.left != None: - cur = cur.left - q.put(cur) - while not q.empty(): - cur = q.get() - lst.append(cur.val) - if cur.right != None: - cur = cur.right - q.put(cur) - while cur.left != None: - cur = cur.left - q.put(cur) - return lst diff --git "a/\346\240\221/100\347\233\270\345\220\214\347\232\204\346\240\221" "b/\346\240\221/100\347\233\270\345\220\214\347\232\204\346\240\221" deleted file mode 100644 index f78c10f..0000000 --- "a/\346\240\221/100\347\233\270\345\220\214\347\232\204\346\240\221" +++ /dev/null @@ -1,47 +0,0 @@ -# 给定两个二叉树,编写一个函数来检验它们是否相同。 -# 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 -# 示例 1: -# 输入: 1 1 -# / \ / \ -# 2 3 2 3 -# -# [1,2,3], [1,2,3] -# 输出: true -# 示例 2: -# 输入: 1 1 -# / \ -# 2 2 -# -# [1,2], [1,null,2] -# 输出: false -# 示例 3: -# 输入: 1 1 -# / \ / \ -# 2 1 1 2 -# -# [1,2,1], [1,1,2] -# -# 输出: false -# def isSameTree(self, p: TreeNode, q: TreeNode) -> bool: - - -# 思路:使用任意一种遍历方式(不能是中序遍历), 记录对应的值, 如果两个列表完全相同, 则是相同的两棵树 -# 但是需要注意一点, 必须把None也记录进去, 否则其实不同的树也是可以遍历出相同的列表的 -# 如果不把None也记录进去, 可以使用两种遍历方式, 把两个树的对应遍历方式进行对比 -# 如果都一致, 则说明两棵树是相同的 - - -class Solution: - def isSameTree(self, p, q): - lst1 = self.helper(p, []) - lst2 = self.helper(q, []) - return lst1 == lst2 - - def helper(self, node, lst): - if not node: - lst.append(None) - return - lst.append(node.val) - self.helper(node.left, lst) - self.helper(node.right, lst) - return lst diff --git "a/\346\240\221/101\345\257\271\347\247\260\347\232\204\346\240\221" "b/\346\240\221/101\345\257\271\347\247\260\347\232\204\346\240\221" deleted file mode 100644 index 9d8850b..0000000 --- "a/\346\240\221/101\345\257\271\347\247\260\347\232\204\346\240\221" +++ /dev/null @@ -1,47 +0,0 @@ -# 给定一个二叉树,检查它是否是镜像对称的。 -# 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 -# 1 -# / \ -# 2 2 -# / \ / \ -# 3 4 4 3 -# 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: -# 1 -# / \ -# 2 2 -# \ \ -# 3 3 -# 说明: -# 如果你可以运用递归和迭代两种方法解决这个问题,会很加分。 -# def isSymmetric(self, root: TreeNode) -> bool: - - -# 思路:使用前序遍历和反向前序遍历, 获取两个列表, 如果两个列表是相同的 -# 说明这是一个对称的二叉树, 需要注意一点, 中序遍历在不记录空节点的情况下 -# 不同的结构的树也是可以获得相同的前序遍历列表的 -# 所以我们需要在遍历的过程中记录空节点 - - -class Solution: - def isSymmetric(self, root): - lst1 = self.inorder(root, []) - lst2 = self.helper(root, []) - return lst1 == lst2 - - def inorder(self, node, lst): - if not node: - lst.append(None) - return - lst.append(node.val) - self.inorder(node.left, lst) - self.inorder(node.right, lst) - return lst - - def helper(self, node, lst): - if not node: - lst.append(None) - return - lst.append(node.val) - self.helper(node.right, lst) - self.helper(node.left, lst) - return lst diff --git "a/\346\240\221/102\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206" "b/\346\240\221/102\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206" deleted file mode 100644 index 94d2ee5..0000000 --- "a/\346\240\221/102\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206" +++ /dev/null @@ -1,40 +0,0 @@ -# 给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。 -# 例如: -# 给定二叉树: [3,9,20,null,null,15,7], -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# 返回其层次遍历结果: -# [ -# [3], -# [9,20], -# [15,7] -# ] -# def levelOrder(self, root: TreeNode) -> List[List[int]]: - - -# 思路:使用队列, 逐层遍历节点存入队列, 取出使放入适当的列表中 -# 注意这里使用了引用传递 -from queue import Queue - - -class Solution: - def levelOrder(self, root): - if not root: - return [] - q = Queue() - q.put((root, 1)) - lst = [] - while not q.empty(): - cur, level = q.get() - if cur.left: - q.put((cur.left, level + 1)) - if cur.right: - q.put((cur.right, level + 1)) - if len(lst) < level: - lst.append([]) - llst = lst[level - 1] - llst.append(cur.val) - return lst diff --git "a/\346\240\221/103\346\240\221\347\232\204\351\224\257\351\275\277\347\212\266\345\261\202\345\272\217\351\201\215\345\216\206" "b/\346\240\221/103\346\240\221\347\232\204\351\224\257\351\275\277\347\212\266\345\261\202\345\272\217\351\201\215\345\216\206" deleted file mode 100644 index 5847e6e..0000000 --- "a/\346\240\221/103\346\240\221\347\232\204\351\224\257\351\275\277\347\212\266\345\261\202\345\272\217\351\201\215\345\216\206" +++ /dev/null @@ -1,58 +0,0 @@ -# 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 -# -# 例如: -# 给定二叉树 [3,9,20,null,null,15,7], -# -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# 返回锯齿形层次遍历如下: -# -# [ -# [3], -# [20,9], -# [15,7] -# ] -# def levelOrder(self, root: TreeNode) -> List[List[int]]: - - -# 思路:此处应该使用栈 -# 参考102树的层序遍历的思路, 103需要在这个基础上改为使用栈结构 -# 在每次获取节点时, 放入栈中, 并且每次获取节点的时候如果节点是属于新层的 -# 那么改变节点的左右子节点的存入顺序 -# 使用两个栈, 一个栈负责上一层, 一个栈负责下一层 -# 当上层的栈为空时, 下层的节点必然已经全部存入下层栈, -# 把下层栈变为上层栈, 生成新的下层栈, 循环进行 -# 直至下层栈的内容为空, 则说明遍历完成 -from queue import LifoQueue - - -class Solution: - def levelOrder(self, root): - if not root: - return [] - q = LifoQueue() - lst = [] - q.put((root, 0)) - while not q.empty(): - q2 = LifoQueue() - while not q.empty(): - cur, level = q.get() - if level > len(lst) - 1: - llst = [] - lst.append(llst) - llst.append(cur.val) - if level % 2: - if cur.right: - q2.put((cur.right, level + 1)) - if cur.left: - q2.put((cur.left, level + 1)) - else: - if cur.left: - q2.put((cur.left, level + 1)) - if cur.right: - q2.put((cur.right, level + 1)) - q = q2 - return lst diff --git "a/\346\240\221/104\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246" "b/\346\240\221/104\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246" deleted file mode 100644 index 5da2504..0000000 --- "a/\346\240\221/104\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246" +++ /dev/null @@ -1,25 +0,0 @@ -# 给定一个二叉树,找出其最大深度。 -# 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 -# 说明: 叶子节点是指没有子节点的节点。 -# 示例: -# 给定二叉树 [3,9,20,null,null,15,7], -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# 返回它的最大深度 3 。 -# def maxDepth(self, root: TreeNode) -> int: - - -# 思路:如果节点为空, 定义高度为0, 然后取左右子树的最大高度 + 1, 用递归太好写了 - - -class Solution: - def maxDepth(self, root): - return self.helper(root) - - def helper(self, node): - if node == None: - return 0 - return max(self.helper(node.left), self.helper(node.right)) + 1 diff --git "a/\346\240\221/105\344\273\216\345\211\215\345\272\217\351\201\215\345\216\206\345\222\214\344\270\255\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\346\240\221" "b/\346\240\221/105\344\273\216\345\211\215\345\272\217\351\201\215\345\216\206\345\222\214\344\270\255\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\346\240\221" deleted file mode 100644 index 6526114..0000000 --- "a/\346\240\221/105\344\273\216\345\211\215\345\272\217\351\201\215\345\216\206\345\222\214\344\270\255\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\346\240\221" +++ /dev/null @@ -1,34 +0,0 @@ -# 根据一棵树的前序遍历与中序遍历构造二叉树。 -# 注意: -# 你可以假设树中没有重复的元素。 -# 例如,给出 -# 前序遍历 preorder = [3,9,20,15,7] -# 中序遍历 inorder = [9,3,15,20,7] -# 返回如下的二叉树: -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: - - -# 思路:从前序找到根,在中序的对应位置,把列表中序列表分成两份, -# 左边为左树的,右边为右树的, -# 注意前序是引用传递然后取出, 中序遍历的列表是深拷贝的 -# 106是从中后序构造一棵树, 比这题要复杂得多, 有时间要去完成 - - -class Solution: - def buildTree(self, preorder, inorder): - return self.helper(preorder,inorder) - - def helper(self, preorder, inorder): - if inorder == []: - return - node = TreeNode(preorder[0]) - index = inorder.index(preorder[0]) - preorder.pop(0) - node.left = self.helper(preorder, inorder[:index]) - node.right = self.helper(preorder, inorder[index+1:]) - return node diff --git "a/\346\240\221/107\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206II" "b/\346\240\221/107\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206II" deleted file mode 100644 index a05be21..0000000 --- "a/\346\240\221/107\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\272\217\351\201\215\345\216\206II" +++ /dev/null @@ -1,40 +0,0 @@ -# 给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) -# 例如: -# 给定二叉树 [3,9,20,null,null,15,7], -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# 返回其自底向上的层次遍历为: -# [ -# [15,7], -# [9,20], -# [3] -# ] -# def levelOrderBottom(self, root: TreeNode) -> List[List[int]]: - - -# 思路:参考层序遍历, 把提交的层序遍历列表的顺序逆转 -from queue import Queue - - -class Solution: - def levelOrderBottom(self, root): - if not root: - return [] - q = Queue() - q.put((root, 1)) - lst = [] - while not q.empty(): - cur, level = q.get() - if cur.left: - q.put((cur.left, level + 1)) - if cur.right: - q.put((cur.right, level + 1)) - if len(lst) < level: - lst.append([]) - llst = lst[level - 1] - llst.append(cur.val) - lst.reverse() - return lst diff --git "a/\346\240\221/108\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\345\271\263\350\241\241\346\220\234\347\264\242\346\240\221" "b/\346\240\221/108\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\345\271\263\350\241\241\346\220\234\347\264\242\346\240\221" deleted file mode 100644 index a9148be..0000000 --- "a/\346\240\221/108\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\345\271\263\350\241\241\346\220\234\347\264\242\346\240\221" +++ /dev/null @@ -1,30 +0,0 @@ -# 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。 -# 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。 -# 示例: -# 给定有序数组: [-10,-3,0,5,9], -# 一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树: -# 0 -# / \ -# -3 9 -# / / -# -10 5 -# def sortedArrayToBST(self, nums: List[int]) -> TreeNode: - - -# 思路:把有序表的中值作为value新建一棵树, 树的左子树和右子树将由剩余的 -# 中值左右两边的列表新建, 递归建树 - - -class Solution: - def sortedArrayToBST(self, nums: List[int]) -> TreeNode: - size = len(nums) - if size < 2: - if size == 0: - return None - root = TreeNode(nums[0]) - return root - mid = int(size/2) - root = TreeNode(nums[mid]) - root.left = self.sortedArrayToBST(nums[:mid]) - root.right = self.sortedArrayToBST(nums[mid+1:]) - return root diff --git "a/\346\240\221/109\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254\351\253\230\345\272\246\345\271\263\350\241\241\346\220\234\347\264\242\346\240\221" "b/\346\240\221/109\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254\351\253\230\345\272\246\345\271\263\350\241\241\346\220\234\347\264\242\346\240\221" deleted file mode 100644 index 86ab190..0000000 --- "a/\346\240\221/109\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254\351\253\230\345\272\246\345\271\263\350\241\241\346\220\234\347\264\242\346\240\221" +++ /dev/null @@ -1,48 +0,0 @@ -# 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。 -# 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。 -# 示例: -# 给定的有序链表: [-10, -3, 0, 5, 9], -# 一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树: -# 0 -# / \ -# -3 9 -# / / -# -10 5 -# def sortedListToBST(self, head: ListNode) -> TreeNode: - - -# 思路:从一般解法上来说, 有序固然跟二叉搜索树是天然契合的, 但是由于链表无法随机访问 -# 导致直接的寻找中值建二叉树变得困难, 这算是链表的特性带来的一个比较重要的不足 -# 解法有很多, 比如先寻找整段链表的中值节点, 把链表分成左右两个链表, 中值做成根节点 -# 然后递归寻找中值节点, 递归建树 -# 但是很明显树用的节点和链表用的节点结构是不一样的, -# 所以其实还是在于值的传递 -# 如果是链表的节点传递当然最好是避免使用列表(与作弊无异), -# 但是这明显是一个传递值构建树的过程, 换言之用链表也是为了传递值, -# 所以强行保持链表属性毫无意义, 所以我选用列表来解答 -# 与其多次重复在链表上移动获取值, 不如直接一次获取所有值并存入列表中来得方便 - - -class Solution: - def sortedListToBST(self, head): - if head == None: - return - lst = [] - # 把值存入列表 - while head != None: - lst.append(head.val) - head = head.next - size = len(lst) - # 递归建树 - node = self.betree(0, size - 1, lst) - return node - - def betree(self, l, r, lst): - # 跟二分搜索很相似 - if l > r: - return - mid = int((l + r) / 2) - node = TreeNode(lst[mid]) - node.left = self.betree(l, mid - 1, lst) - node.right = self.betree(mid + 1, r, lst) - return node diff --git "a/\346\240\221/111\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246" "b/\346\240\221/111\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246" deleted file mode 100644 index b02b53f..0000000 --- "a/\346\240\221/111\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246" +++ /dev/null @@ -1,33 +0,0 @@ -# 给定一个二叉树,找出其最小深度。 -# 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 -# 说明: 叶子节点是指没有子节点的节点。 -# 示例: -# 给定二叉树 [3,9,20,null,null,15,7], -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# 返回它的最小深度  2. -# def minDepth(self, root: TreeNode) -> int: - - -# 思路:空节点默认值为最大值(此处取巧设为10000, -# 因为我认为题中不会出现深度最低为10000的树), -# 叶节点高度为1, 然后每个节点比较取最小值然后+1 - - -class Solution: - def minDepth(self, root): - if root == None: - return 0 - return self.helper(root) - - def helper(self, node): - if node == None: - return 10000 - if node.left == None and node.right == None: - return 1 - res1 = self.helper(node.left) - res2 = self.helper(node.right) - return min(res1, res2) + 1 diff --git "a/\346\240\221/112\350\267\257\345\276\204\344\271\213\345\222\214" "b/\346\240\221/112\350\267\257\345\276\204\344\271\213\345\222\214" deleted file mode 100644 index 8a27b50..0000000 --- "a/\346\240\221/112\350\267\257\345\276\204\344\271\213\345\222\214" +++ /dev/null @@ -1,32 +0,0 @@ -# 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。 -# 说明: 叶子节点是指没有子节点的节点。 -# 示例:  -# 给定如下二叉树,以及目标和 sum = 22, -# 5 -# / \ -# 4 8 -# / / \ -# 11 13 4 -# / \ \ -# 7 2 1 -# 返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。 -# def hasPathSum(self, root: TreeNode, sum: int) -> bool: - - -# 思路:这里主要要用到一个比较少见的概念, 叶节点判断, 含义就是要判断这个节点 -# 是否是一个叶节点, 比如例子中8-4-1中的4就不会叶节点, 因为他虽然左子树是空 -# 但是他右子树不是空, 叶节点要求就是左右子树都为空, 所以只要判断从根到所有叶节点 -# 的和中存在和为目标值的, 就返回True -# 关联题目113, 437 - - -class Solution: - def hasPathSum(self, root, sum): - return self.helper(root, sum) - - def helper(self, node, sum): - if not node: - return - if not node.left and not node.right and node.val == sum: - return True - return self.helper(node.left, sum-node.val) or self.helper(node.right, sum-node.val) diff --git "a/\346\240\221/113\350\267\257\345\276\204\344\271\213\345\222\214II" "b/\346\240\221/113\350\267\257\345\276\204\344\271\213\345\222\214II" deleted file mode 100644 index 6deb062..0000000 --- "a/\346\240\221/113\350\267\257\345\276\204\344\271\213\345\222\214II" +++ /dev/null @@ -1,40 +0,0 @@ -# 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 -# 说明: 叶子节点是指没有子节点的节点。 -# 示例: -# 给定如下二叉树,以及目标和 sum = 22, -# 5 -# / \ -# 4 8 -# / / \ -# 11 13 4 -# / \ / \ -# 7 2 5 1 -# 返回: -# [ -# [5,4,11,2], -# [5,8,4,5] -# ] -# def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: - - -# 思路:这题应该是用深度遍历, 由于是树这种结构, 所以采用递归, -# 加上前面提到的叶节点判断方法, 这道题迎刃而解 -# 关联题目112, 437(更复杂一丢丢) - - -class Solution: - def pathSum(self, root, sum): - if not root: - return [] - self.res = [] - self.helper(root, sum, []) - return self.res - - def helper(self, node, sum, lst): - if not node: - return - lst.append(node.val) - if not node.left and not node.right and sum == node.val: - self.res.append(lst[:]) - self.helper(node.left, sum - node.val, lst[:]) - self.helper(node.right, sum - node.val, lst[:]) diff --git "a/\346\240\221/116\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\346\214\207\351\222\210\350\212\202\347\202\271" "b/\346\240\221/116\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\346\214\207\351\222\210\350\212\202\347\202\271" deleted file mode 100644 index 18855eb..0000000 --- "a/\346\240\221/116\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\346\214\207\351\222\210\350\212\202\347\202\271" +++ /dev/null @@ -1,39 +0,0 @@ -# 给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下: -# struct Node { -# int val; -# Node *left; -# Node *right; -# Node *next; -# } -# 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。 -# 初始状态下,所有 next 指针都被设置为 NULL。 -# def connect(self, root: 'Node') -> 'Node': - - -# 思路:在层序遍历的基础上, 把每一层中获取的节点连接上下一个获取的节点 -from queue import Queue - - -class Solution: - def connect(self, root): - if not root: - return - q = Queue() - q.put((root, 0)) - # 初始化res的第二个参数为-1, 说明第一次取出的root为新层节点 - res = (0, -1) - while not q.empty(): - cur, level = q.get() - if cur.left: - q.put((cur.left, level+1)) - if cur.right: - q.put((cur.right, level+1)) - # 如果到了新层的第一个节点, 用res记录这个节点和所在层数 - if level > res[1]: - res = (cur, level) - # 其余的节点, 都是先把前一个节点(刚才把新层的第一个节点存入了)指向这个节点 - # 然后把当前节点存入res, 循环进行 - else: - res[0].next = cur - res = (cur, level) - return root diff --git "a/\346\240\221/230\346\237\245\346\211\276\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\347\254\254K\345\260\217\345\205\203\347\264\240" "b/\346\240\221/230\346\237\245\346\211\276\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\347\254\254K\345\260\217\345\205\203\347\264\240" deleted file mode 100644 index 9df77c4..0000000 --- "a/\346\240\221/230\346\237\245\346\211\276\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\347\254\254K\345\260\217\345\205\203\347\264\240" +++ /dev/null @@ -1,44 +0,0 @@ -# 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。 -# 说明: -# 你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。 -# 示例 1: -# 输入: root = [3,1,4,null,2], k = 1 -# 3 -# / \ -# 1 4 -# \ -#   2 -# 输出: 1 -# 示例 2: -# 输入: root = [5,3,6,2,4,null,null,1], k = 3 -# 5 -# / \ -# 3 6 -# / \ -# 2 4 -# / -# 1 -# 输出: 3 -# def kthSmallest(self, root: TreeNode, k: int) -> int: - - -# 思路:中序遍历,第k次的答案就是了,在递归的中序遍历的写法中增加一个判断变量 -# 由于中序遍历其实也是深度优先的一种, 所以这里有点回溯法的感觉 - - -class Solution: - def kthSmallest(self, root, k): - self.num = 1 - self.res = 0 - self.dfs(root, k) - return self.res - - def dfs(self, node, k): - if self.num > k: - return - if node != None: - self.dfs(node.left, k) - if self.num == k: - self.res = node.val - self.num += 1 - self.dfs(node.right, k) diff --git "a/\346\240\221/235\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210" "b/\346\240\221/235\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210" deleted file mode 100644 index 8eee218..0000000 --- "a/\346\240\221/235\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210" +++ /dev/null @@ -1,33 +0,0 @@ -# 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 -# 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” -# 例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5] -# 示例 1: -# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 -# 输出: 6 -# 解释: 节点 2 和节点 8 的最近公共祖先是 6。 -# 示例 2: -# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 -# 输出: 2 -# 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。 -# 注:这是二分搜索树,且所有节点值唯一 -# def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': - - -# 思路:两个值有较大较小者,从根节点开始,如果下沉遇到了节点是二者之一 -# (且下沉方向相同),说明这个节点是另一个节点的祖先, -# 如果下沉方向不同,说明上一层的节点就是公共祖先 -# 还有236题跟这题很像, 不过复杂一些, 有很巧妙的解法 - - -class Solution: - def lowestCommonAncestor(self, root, p, q): - maxval = max(p.val, q.val) - minval = min(p.val, q.val) - while not (root.val == maxval or root.val == minval): - if minval < root.val < maxval: - return root - elif root.val > maxval: - root = root.left - elif root.val < minval: - root = root.right - return root diff --git "a/\346\240\221/236\346\227\240\345\272\217\346\240\221\344\270\255\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210" "b/\346\240\221/236\346\227\240\345\272\217\346\240\221\344\270\255\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210" deleted file mode 100644 index b940510..0000000 --- "a/\346\240\221/236\346\227\240\345\272\217\346\240\221\344\270\255\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210" +++ /dev/null @@ -1,35 +0,0 @@ -# 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 -# 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” -# 例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4] -# 示例 1: -# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 -# 输出: 3 -# 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 -# 示例 2: -# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 -# 输出: 5 -# 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。 -# def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': - - -# 思路:从235看到236, 由于变得无序, 感觉会变得没有规律 -# 其实这里重点是把握住核心问题:把一棵二叉树看成三部分, 分别是中, 左子树, 右子树 -# 如果中就是要找的其中一棵树, 那么另一棵树肯定在他的子树里, 那根节点自己就是公共祖先 -# 否则分别对左右子树进行深度优先遍历, 如果遇到了要找的树的其中一棵, 返回对应节点, -# 如果一直找下去都找不到, 返回空, 从根节点开始往下找, 如果只找到一棵树, 说明另一棵树 -# 藏在这棵树的子树里, 所以这棵树就是公共祖先 -# 如果左右各有一棵树, 说明目前这棵树是要寻找的两棵树的公共祖先 - - -class Solution: - def lowestCommonAncestor(self, root, p, q): - if root == None or root == p or root == q: - return root - left = self.lowestCommonAncestor(root.left, p, q) - right = self.lowestCommonAncestor(root.right, p, q) - if left != None and right != None: - return root - if left != None: - return left - else: - return right diff --git "a/\346\240\221/404\345\267\246\345\217\266\344\271\213\345\222\214" "b/\346\240\221/404\345\267\246\345\217\266\344\271\213\345\222\214" deleted file mode 100644 index 7ff4677..0000000 --- "a/\346\240\221/404\345\267\246\345\217\266\344\271\213\345\222\214" +++ /dev/null @@ -1,30 +0,0 @@ -# 计算给定二叉树的所有左叶子之和。 -# 示例: -# 3 -# / \ -# 9 20 -# / \ -# 15 7 -# 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24 -# def sumOfLeftLeaves(self, root: TreeNode) -> int: - - -# 思路:这里用到了一个小技巧:叶节点判断, 在一些题中会遇到, 如果有叶节点判断这种 -# 概念的话, 有些问题会变得很容易解答, 这里用叶节点判断+一个参数来证明他是左节点还是右节点 - - -class Solution: - def sumOfLeftLeaves(self, root): - self.val = 0 - self.left(root) - return self.val - - - def left(self, node, isleft=False): - if node == None: - return 0 - if node.left == None and node.right == None and isleft == True: - self.val += node.val - return self.val - self.left(node.left, True) - self.left(node.right) diff --git "a/\346\240\221/437\350\267\257\345\276\204\344\271\213\345\222\214III" "b/\346\240\221/437\350\267\257\345\276\204\344\271\213\345\222\214III" deleted file mode 100644 index 8adac59..0000000 --- "a/\346\240\221/437\350\267\257\345\276\204\344\271\213\345\222\214III" +++ /dev/null @@ -1,41 +0,0 @@ -# 给定一个二叉树,它的每个结点都存放着一个整数值。 -# 找出路径和等于给定数值的路径总数。 -# 路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。 -# 二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。 -# 示例: -# root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 -# 10 -# / \ -# 5 -3 -# / \ \ -# 3 2 11 -# / \ \ -# 3 -2 1 -# 返回 3。和等于 8 的路径有: -# 1. 5 -> 3 -# 2. 5 -> 2 -> 1 -# 3. -3 -> 11 -# def pathSum(self, root: TreeNode, sum: int) -> int: -# 思路:核心就是在原来的路径和函数基础上加上树的遍历,所以用双递归 - - -class Solution: - - def __init__(self): - self.val = 0 - - def pathSum(self, root, sum): - if not root: - return 0 - self.findpath(root, sum) - self.pathSum(root.left, sum) - self.pathSum(root.right, sum) - return self.val - - def findpath(self, node, sum): - if not node: - return 0 - if node.val == sum: - self.val += 1 - self.findpath(node.left, sum - node.val) - self.findpath(node.right, sum - node.val) diff --git "a/\346\240\221/559N\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246" "b/\346\240\221/559N\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246" deleted file mode 100644 index 0d16e6f..0000000 --- "a/\346\240\221/559N\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246" +++ /dev/null @@ -1,33 +0,0 @@ -# 给定一个 N 叉树,找到其最大深度。 -# 最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。 -# 例如,给定一个 3叉树 : -# 我们应返回其最大深度,3。 -# 说明: -# 树的深度不会超过 1000。 -# 树的节点总不会超过 5000。 -# """ -# # Definition for a Node. -# class Node: -# def __init__(self, val, children): -# self.val = val -# self.children = children -# """ -# def maxDepth(self, root: 'Node') -> int: - - -# 思路:基本和二叉树的最大深度相似, 不过此处的children是一个节点集, 所以要for循环 - - -class Solution: - def maxDepth(self, root): - return self.helper(root) - - def helper(self, node): - if node == None: - return 0 - if node.children == []: - return 1 - total = 0 - for i in node.children: - total = max(self.helper(i), total) - return total + 1 diff --git "a/\346\240\221/98\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221" "b/\346\240\221/98\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221" deleted file mode 100644 index 9306086..0000000 --- "a/\346\240\221/98\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221" +++ /dev/null @@ -1,47 +0,0 @@ -# 给定一个二叉树,判断其是否是一个有效的二叉搜索树。 -# 假设一个二叉搜索树具有如下特征: -# 节点的左子树只包含小于当前节点的数。 -# 节点的右子树只包含大于当前节点的数。 -# 所有左子树和右子树自身必须也是二叉搜索树。 -# 示例 1: -# 输入: -# 2 -# / \ -# 1 3 -# 输出: true -# 示例 2: -# 输入: -# 5 -# / \ -# 1 4 -#   / \ -#   3 6 -# 输出: false -# 解释: 输入为: [5,1,4,null,null,3,6]。 -#   根节点的值为 5 ,但是其右子节点值为 4 。 -# def isValidBST(self, root: TreeNode) -> bool: - - -# 思路:这个题目考查的是二叉搜索树性质, 由于二叉搜索树的中序遍历是一个升序列表 -# 如果遍历发现不是升序列表, 则说明不是搜索树 - - -class Solution: - def isValidBST(self, root): - if not root: - return True - res = self.inorder(root, []) - rec = res[0] - 1 - for i in res: - if rec >= i: - return False - rec = i - return True - - def inorder(self, node, lst): - if not node: - return - self.inorder(node.left, lst) - lst.append(node.val) - self.inorder(node.right, lst) - return lst diff --git "a/\346\240\221/99\346\201\242\345\244\215\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221" "b/\346\240\221/99\346\201\242\345\244\215\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221" deleted file mode 100644 index 9abdc91..0000000 --- "a/\346\240\221/99\346\201\242\345\244\215\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221" +++ /dev/null @@ -1,46 +0,0 @@ -# 二叉搜索树中的两个节点被错误地交换。 -# 请在不改变其结构的情况下,恢复这棵树。 -# 示例 1: -# 输入: [1,3,null,null,2] -#   1 -#   / -#  3 -#   \ -#   2 -# 输出: [3,1,null,null,2] -#   3 -#   / -#  1 -#   \ -#   2 -# def recoverTree(self, root: TreeNode) -> None: - - -# 思路:首先这个问题的相关内容我仔细检验过, 只需要更换两个节点的值, 而不改变结构 -# 中序遍历二叉搜索树应该获得一个升序列表, 既然错误的更换了两个节点的值, 则获得的 -# 则不是一个升序列表, 而且应该是只有两个位置错误的升序列表 -# 所以我们只需要把节点记录下来, 并且找到他们对应的位置, 交换两个位置的值 - - -class Solution: - def recoverTree(self, root): - if not root: - return - lst1, lst2 = self.helper(root, [], []) - lst = sorted(lst1) - lst8 = [] - for i in range(len(lst)): - if lst[i] != lst1[i]: - lst8.append(i) - lst2[lst8[0]].val, lst2[lst8[1]].val = lst2[lst8[1]].val, lst2[lst8[0]].val - return - - - def helper(self, node, lst1, lst2): - if not node: - return - self.helper(node.left, lst1, lst2) - lst1.append(node.val) - lst2.append(node) - self.helper(node.right, lst1, lst2) - return lst1, lst2 diff --git "a/\350\247\204\345\276\213\351\242\230/118\346\235\250\350\276\211\344\270\211\350\247\222" "b/\350\247\204\345\276\213\351\242\230/118\346\235\250\350\276\211\344\270\211\350\247\222" deleted file mode 100644 index 085d5d1..0000000 --- "a/\350\247\204\345\276\213\351\242\230/118\346\235\250\350\276\211\344\270\211\350\247\222" +++ /dev/null @@ -1,31 +0,0 @@ -# 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。 -# 在杨辉三角中,每个数是它左上方和右上方的数的和。 -# 示例: -# 输入: 5 -# 输出: -# [ -# [1], -# [1,1], -# [1,2,1], -# [1,3,3,1], -# [1,4,6,4,1] -# ] -# def generate(self, numRows: int) -> List[List[int]]: - - -# 思路:直接制作一个拥有第一行答案的列表, 然后从第二行开始 -# 默认创建一个拥有两个1值的列表, 如果当前行超过2, 则用上一行的对应索引和索引-1的值求和 -# 直至完全填充numrows行 - - -class Solution: - def generate(self, numRows): - if numRows == 0: - return [] - dp = [[1]] - for i in range(1, numRows): - lst = [1, 1] - for j in range(i-1): - lst.insert(j+1, dp[i-1][j]+dp[i-1][j+1]) - dp.append(lst) - return dp diff --git "a/\350\247\204\345\276\213\351\242\230/11\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250" "b/\350\247\204\345\276\213\351\242\230/11\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250" deleted file mode 100644 index 82577c7..0000000 --- "a/\350\247\204\345\276\213\351\242\230/11\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250" +++ /dev/null @@ -1,35 +0,0 @@ -# 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点 -# 分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 -# 说明:你不能倾斜容器,且 n 的值至少为 2。 -# 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 -# 示例: -# 输入: [1,8,6,2,5,4,8,3,7] -# 输出: 49 -# def maxArea(self, height: List[int]) -> int: - - -# 思路:这道题其实规律是很简单的, 但是想要看出规律或者证明规律却很难, 我简单指出这个规律 -# 在这么多高低不同的木板构成的区域中, 能够盛最多水的区域是哪一个不好判断, 但是我们可以 -# 通过缩小宽度来寻找下一种储水量更大的可能性, 找出其中储水量最大的可能性就是结果 -# 这个规律是什么? 我们可以假设宽度完整的时候, 能盛的水是最多的, 然后找寻下一个盛更多水的可能性 -# 这个可能性要怎么去找呢? 减少宽度, 看看能不能增加存水的高度 -# 其实就是让两个指针从两边往中间走, 他的宽度是一直在降低的, -# 同时给一个判断, 如果左右指针的高度不同, 则高的指针停下, 矮的指针移动 -# 这意味着我们一直在往更大的储水量的可能性发展 -# 一直往中间靠拢, 直至宽度为1, 这里面一定包含了盛水量最大的可能性, 然后比较各种宽度下最大的 -# 盛水量, 求出所有宽度下最大盛水量 - - -class Solution: - def maxArea(self, height): - l = 0 - r = len(height) - 1 - res = 0 - while l < r: - if height[l] < height[r]: - res = max(min(height[l], height[r]) * (r - l), res) - l += 1 - else: - res = max(min(height[l], height[r]) * (r - l), res) - r -= 1 - return res diff --git "a/\350\247\204\345\276\213\351\242\230/12\346\225\264\346\225\260\350\275\254\347\275\227\351\251\254\346\225\260\345\255\227" "b/\350\247\204\345\276\213\351\242\230/12\346\225\264\346\225\260\350\275\254\347\275\227\351\251\254\346\225\260\345\255\227" deleted file mode 100644 index b160959..0000000 --- "a/\350\247\204\345\276\213\351\242\230/12\346\225\264\346\225\260\350\275\254\347\275\227\351\251\254\346\225\260\345\255\227" +++ /dev/null @@ -1,55 +0,0 @@ -# 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 -# 字符 数值 -# I 1 -# V 5 -# X 10 -# L 50 -# C 100 -# D 500 -# M 1000 -# 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。 -# 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边, -# 所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: -# I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 -# X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。  -# C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 -# 给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。 -# 示例 1: -# 输入: 3 -# 输出: "III" -# 示例 2: -# 输入: 4 -# 输出: "IV" -# 示例 3: -# 输入: 9 -# 输出: "IX" -# 示例 4: -# 输入: 58 -# 输出: "LVIII" -# 解释: L = 50, V = 5, III = 3. -# 示例 5: -# 输入: 1994 -# 输出: "MCMXCIV" -# 解释: M = 1000, CM = 900, XC = 90, IV = 4. -# def intToRoman(self, num: int) -> str: - - -# 思路:这里最重要的是给一种优先的概念, 要知道存在的罗马数字值中, 更大的具有更优先的表达顺序 -# 比如遇到10我们理论上可以表达为X和VV, 但是正确的选择是X, 是因为10是存在罗马数字的值中的 -# 并且更大,然后就是构造对应关系, 把数字和罗马数字进行转换 -# 这里可以使用字典, 但是考虑到字典是无序的, 比较难构造优先关系, 所以我将数字和罗马数字 -# 对应的且逆序地放在两个数组中, 这样就从左往右遍历就可以达到优先和对应转换的效果 - - -class Solution: - def intToRoman(self, num): - nums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1] - lst = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"] - res = '' - index = 0 - while num > 0: - while index < 14 and num < nums[index]: - index += 1 - res += lst[index] - num -= nums[index] - return res diff --git "a/\350\247\204\345\276\213\351\242\230/13\347\275\227\351\251\254\346\225\260\345\255\227\350\275\254\346\225\264\345\236\213" "b/\350\247\204\345\276\213\351\242\230/13\347\275\227\351\251\254\346\225\260\345\255\227\350\275\254\346\225\264\345\236\213" deleted file mode 100644 index 5e88ccc..0000000 --- "a/\350\247\204\345\276\213\351\242\230/13\347\275\227\351\251\254\346\225\260\345\255\227\350\275\254\346\225\264\345\236\213" +++ /dev/null @@ -1,68 +0,0 @@ -# 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 -# 字符 数值 -# I 1 -# V 5 -# X 10 -# L 50 -# C 100 -# D 500 -# M 1000 -# 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。 -# 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边, -# 所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: -# I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 -# X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。  -# C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 -# 给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。 -# 示例 1: -# 输入: "III" -# 输出: 3 -# 示例 2: -# 输入: "IV" -# 输出: 4 -# 示例 3: -# 输入: "IX" -# 输出: 9 -# 示例 4: -# 输入: "LVIII" -# 输出: 58 -# 解释: L = 50, V= 5, III = 3. -# 示例 5: -# 输入: "MCMXCIV" -# 输出: 1994 -# 解释: M = 1000, CM = 900, XC = 90, IV = 4. -# def romanToInt(self, s: str) -> int: - - -# 思路:这道题比上一道稍稍复杂一点点, 在上一题的逆序构成优先级和对应转换的基础上 -# 增加一个判断, 用于正确判断出IV是9而不是11, 这里的做法是用两个字符来判断, 如果有符合 -# 的, 则直接转换, 如果没有符合的, 则转换一个字符 -# 由于这里的优先级不是对于数值的, 而是对于出现的字符串的判断, 所以我将使用字典作为容器 -# 这样可以避免使用循环来检查数组 - - -class Solution: - def romanToInt(self, s): - if s == '': - return 0 - dct = {'M': 1000, 'CM': 900, 'D': 500, 'CD': 400, - 'C': 100, 'XC': 90, 'L': 50, 'XL': 40, 'X': 10, - 'IX': 9, 'V': 5, 'IV': 4, 'I': 1} - index = 0 - size = len(s) - res = 0 - while index < size: - if index != size - 1: - total = s[index:index+2] - if total in dct: - res += dct[total] - index += 2 - else: - total = s[index] - res += dct[total] - index += 1 - else: - total = s[index] - res += dct[total] - index += 1 - return res diff --git "a/\350\247\204\345\276\213\351\242\230/14\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200" "b/\350\247\204\345\276\213\351\242\230/14\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200" deleted file mode 100644 index 2576767..0000000 --- "a/\350\247\204\345\276\213\351\242\230/14\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200" +++ /dev/null @@ -1,39 +0,0 @@ -# 编写一个函数来查找字符串数组中的最长公共前缀。 -# 如果不存在公共前缀,返回空字符串 ""。 -# 示例 1: -# 输入: ["flower","flow","flight"] -# 输出: "fl" -# 示例 2: -# 输入: ["dog","racecar","car"] -# 输出: "" -# 解释: 输入不存在公共前缀。 -# 说明: -# 所有输入只包含小写字母 a-z 。 -# def longestCommonPrefix(self, strs: List[str]) -> str: - - -# 思路:直接取列表内第一个字符串作为初始答案, 因为最长公共前缀不可能超过 -# 任何一个列表内的字符串, 然后遍历所有字符串, 跟初始答案比较, 如果 -# 相同部分比初始答案也少, 重置初始答案为相同部分, -# 直至答案为空字符串或列表遍历完毕 - - -class Solution: - def longestCommonPrefix(self, strs): - if strs == []: - return '' - res = strs.pop(0) - for i in strs: - if i == '' or res == '': - return '' - k = 1 - for j in range(min(len(res), len(i))): - if res[j] != i[j]: - if j == 0: - return '' - k = 0 - break - if k == 1: - j += 1 - res = res[:j] - return res diff --git "a/\350\247\204\345\276\213\351\242\230/15\344\270\211\346\225\260\344\271\213\345\222\214" "b/\350\247\204\345\276\213\351\242\230/15\344\270\211\346\225\260\344\271\213\345\222\214" deleted file mode 100644 index e05ec30..0000000 --- "a/\350\247\204\345\276\213\351\242\230/15\344\270\211\346\225\260\344\271\213\345\222\214" +++ /dev/null @@ -1,46 +0,0 @@ -# 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在 -# 三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。 -# 注意:答案中不可以包含重复的三元组。 -# 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], -# 满足要求的三元组集合为: -# [ -# [-1, 0, 1], -# [-1, -1, 2] -# ] -# def threeSum(self, nums: List[int]) -> List[List[int]]: - - -# 思路:这题最典型的就是暴力破解复杂度是O(N3), -# 这类 在一个固定数组上进行多次循环 的问题, -# 很大概率可以使用碰撞指针的思路, 两个指针分别从两边往中间 -# 靠拢直至两个指针重合, 先要把数组排序, 还有一个剪枝操作 -# 如果第三个游动的指针本身已经大于等于零, 可以直接结束 -# 由于不允许重复答案, 所以用集合来储存 - - -class Solution: - def threeSum(self, nums): - nums.sort() - ans = set() - size = len(nums) - mid = 0 - while mid < size - 2: - l = mid + 1 - r = size - 1 - while l < r: - temp = nums[mid] + nums[l] + nums[r] - if temp == 0: - ans.add((nums[mid], nums[l], nums[r])) - l += 1 - r -= 1 - elif temp < 0: - l += 1 - else: - r -= 1 - if nums[mid] >= 0: - break - mid += 1 - res = [] - for i in ans: - res.append(list(i)) - return res diff --git "a/\350\247\204\345\276\213\351\242\230/18\345\233\233\346\225\260\344\271\213\345\222\214" "b/\350\247\204\345\276\213\351\242\230/18\345\233\233\346\225\260\344\271\213\345\222\214" deleted file mode 100644 index 0faf273..0000000 --- "a/\350\247\204\345\276\213\351\242\230/18\345\233\233\346\225\260\344\271\213\345\222\214" +++ /dev/null @@ -1,50 +0,0 @@ -# 给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个 -# 元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件 -# 且不重复的四元组。 -# 注意: -# 答案中不可以包含重复的四元组。 -# 示例: -# 给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 -# 满足要求的四元组集合为: -# [ -# [-1, 0, 0, 1], -# [-2, -1, 1, 2], -# [-2, 0, 0, 2] -# ] -# def fourSum(self, nums: List[int], target: int) -> List[List[int]]: - - -# 思路:针对这种在同一个数组上进行多次循环的问题, 大概率可以使用指针碰撞 -# 降低复杂度, 要计算四数之和, 这里将先把数组排序 -# 然后用两个指针各自进行列表遍历 -# 然后左右指针在另外两个指针的对应情况下求组合的和进行指针碰撞 -# 照样先使用集合和元组来储存 - - -class Solution: - def fourSum(self, nums, target): - size = len(nums) - nums.sort() - ans = set() - midl = 0 - while midl < size - 3: - midr = midl + 1 - while midr < size - 2: - l = midr + 1 - r = size - 1 - while l < r: - temp = nums[midl] + nums[midr] + nums[l] + nums[r] - if temp == target: - ans.add((nums[midl], nums[midr], nums[l], nums[r])) - l += 1 - r -= 1 - elif temp < target: - l += 1 - else: - r -= 1 - midr += 1 - midl += 1 - res = [] - for i in ans: - res.append(list(i)) - return res diff --git "a/\350\247\204\345\276\213\351\242\230/27\345\216\237\345\234\260\344\277\256\346\224\271\346\225\260\347\273\204\347\247\273\351\231\244\345\205\203\347\264\240" "b/\350\247\204\345\276\213\351\242\230/27\345\216\237\345\234\260\344\277\256\346\224\271\346\225\260\347\273\204\347\247\273\351\231\244\345\205\203\347\264\240" deleted file mode 100644 index 8794f66..0000000 --- "a/\350\247\204\345\276\213\351\242\230/27\345\216\237\345\234\260\344\277\256\346\224\271\346\225\260\347\273\204\347\247\273\351\231\244\345\205\203\347\264\240" +++ /dev/null @@ -1,31 +0,0 @@ -# 给定一个数组 nums 和一个值 val,、你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。 -# 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 -# 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 -# 示例 1: -# 给定 nums = [3,2,2,3], val = 3, -# 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 -# 你不需要考虑数组中超出新长度后面的元素。 -# 示例 2: -# 给定 nums = [0,1,2,2,3,0,4,2], val = 2, -# 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。 -# 注意这五个元素可为任意顺序。 -# 你不需要考虑数组中超出新长度后面的元素。 -# def removeElement(self, nums: List[int], val: int) -> int: - - -# 思路:这道题的解法和26的原地删除重复项很相似, 甚至更加简单, -# 由于不像原地删除重复项的要求的值会一直变化, 所以这里的数组不需要是 -# 有序的, 只要使用快慢指针, 让快指针先跑, 把合乎要求的值,放到慢指针的 -# 位置, 这样慢指针部分的值, 就全部都不为value了 -# 注意, 这里和原地删除重复项有少许不同, 这里的慢指针是指向将要被更改的位置 -# 所以这里return 慢指针的索引就是正确的答案了 - - -class Solution: - def removeElement(self, nums, val): - i = 0 - for j in range(len(nums)): - if nums[j] != val: - nums[i], nums[j] = nums[j], nums[i] - i += 1 - return i diff --git "a/\350\247\204\345\276\213\351\242\230/28\345\255\227\347\254\246\344\270\262\347\232\204find\346\226\271\346\263\225" "b/\350\247\204\345\276\213\351\242\230/28\345\255\227\347\254\246\344\270\262\347\232\204find\346\226\271\346\263\225" deleted file mode 100644 index 463ea77..0000000 --- "a/\350\247\204\345\276\213\351\242\230/28\345\255\227\347\254\246\344\270\262\347\232\204find\346\226\271\346\263\225" +++ /dev/null @@ -1,39 +0,0 @@ -# 实现 strStr() 函数。 -# 给定一个 haystack 字符串和一个 needle 字符串, -# 在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。 -# 如果不存在,则返回  -1。 -# 示例 1: -# 输入: haystack = "hello", needle = "ll" -# 输出: 2 -# 示例 2: -# 输入: haystack = "aaaaa", needle = "bba" -# 输出: -1 -# 说明: -# 当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。 -# 对于本题而言,当 needle 是空字符串时我们应当返回 0 。 -# 这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。 -# def strStr(self, haystack: str, needle: str) -> int: - - -# 思路:这其实就是字符串的find方法, -# 解题思路先找到首字母相同的, 然后对比字数长度的一段是否一致 -# 这思路跟滑动窗口很像了, 也可以使用滑动窗口来写 - - -class Solution: - def strStr(self, haystack, needle): - size = len(needle) - if size < 1: - return 0 - for i in range(len(haystack)-size+1): - if haystack[i] == needle[0]: - ha = haystack[i:i + size] - # 也可以直接查, if ha == needle:return i - k = 0 - for j in range(size): - if ha[j] != needle[j]: - k = 1 - break - if k == 1: - return i - return -1 diff --git "a/\350\247\204\345\276\213\351\242\230/31\345\233\236\346\272\257\347\232\204\344\270\213\344\270\200\347\247\215\345\217\257\350\203\275" "b/\350\247\204\345\276\213\351\242\230/31\345\233\236\346\272\257\347\232\204\344\270\213\344\270\200\347\247\215\345\217\257\350\203\275" deleted file mode 100644 index 219fe77..0000000 --- "a/\350\247\204\345\276\213\351\242\230/31\345\233\236\346\272\257\347\232\204\344\270\213\344\270\200\347\247\215\345\217\257\350\203\275" +++ /dev/null @@ -1,63 +0,0 @@ -# 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。 -# 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。 -# 必须原地修改,只允许使用额外常数空间。 -# 以下是一些例子,输入位于左侧列,其相应输出位于右侧列。 -# 3,2,1 → 1,2,3 -# 1,1,5 → 1,5,1 -# def nextPermutation(self, nums: List[int]) -> None: - - -# 思路:首先这道题题目解释完全不能理解, 在看了其他人的解释之后我给出了一个更容易看懂的解释 -# 这道题不使用回溯, 但是跟回溯、全排列关系十分密切, 因为回溯其实是一种思想, 一种关于有顺序的 -# 获取符合题意的所有可能并在过程中(在index == n 之前)筛选出合理可能(剪枝)的思想, -# 有序地获取所有可能恰恰就是全排列的思路 -# 以123456为例, 把这6个数不重复的使用组合出的可能共有A6(6)即6!种,按照全排列的正常顺序输出 -# 应该是123456, 123465, 123456, 123564 …… 到最后一种654321, 题目输入一种可能性, 我们的结果 -# 就输出下一种可能性, 如果题目输入最后一种可能性, 那么我们就输出第一种可能性 -# 那么基本的回应机制就是, 1)如果参数是最后一种可能性, 我们就返回第一种 -# 2)如果倒数第一个数比倒数第二个数大, 则只调换这两个数 -# 3)如果后面有一段倒序的数, 那按照全排列的思路去分析, 应该轮到这段倒序的数的前一个数变大了(其实第2种是第3种的子集) - - -class Solution: - def nextPermutation(self, nums): - size = len(nums) - # 小于2个数不用管 - if size < 2: - return - # 上面提到的第二种可能 - if nums[-1] > nums[-2]: - nums[-1], nums[-2] = nums[-2], nums[-1] - return - maxinum = 0 - rec = nums[-1] - for i in range(1, size + 1): - if maxinum < nums[-i]: - maxinum = nums[-1] - if nums[-i] < rec: - break - else: - rec = nums[-i] - # 上面提到的第一种可能 - if i == size and nums[0] >= nums[1]: - nums.reverse() - return - # 上面提到的第三种可能, 需要以下操作 - # 刚才-i(因为我是从右往左数的)就是123765中的3所在的位, 现在我要寻找一个比3而且最接近3的位 - if nums[-1] > nums[-i]: # 如果倒数第一位就比-i位的数大, 直接交换, 因为倒数第2,3,4位只会更大 - nums[-1], nums[-i] = nums[-i], nums[-1] - else: - # 如果倒数第一位没有-i位大, 那就需要好好分析了, 先假设是-i+1位的数(因为他是[-i:-1]这段中最大的数) - # 如果找到一个比他更贴近-i位的值的位, 更新为k, 并交换 - # 结果就会从 126 865 变成 128 665(-3位和-4位交换) 最后将后半段翻转一下 - total = nums[-i + 1] - nums[-i] - k = i - 1 - for j in range(1, i): - total = nums[-j] - nums[-i] - if 0 < total < rec: - k = j - rec = total - nums[-i], nums[-k] = nums[-k], nums[-i] - mid = int(i / 2 - 0.5) - for j in range(1, mid + 1): - nums[-j], nums[-(i - j)] = nums[-(i - j)], nums[-j] diff --git "a/\350\247\204\345\276\213\351\242\230/34\346\234\211\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\344\275\215\347\275\256\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256" "b/\350\247\204\345\276\213\351\242\230/34\346\234\211\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\344\275\215\347\275\256\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256" deleted file mode 100644 index 2f2f836..0000000 --- "a/\350\247\204\345\276\213\351\242\230/34\346\234\211\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\344\275\215\347\275\256\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256" +++ /dev/null @@ -1,41 +0,0 @@ -# 给定一个按照升序排列的整数数组 nums,和一个目标值 -# target。找出给定目标值在数组中的开始位置和结束位置。 -# 你的算法时间复杂度必须是 O(log n) 级别。 -# 如果数组中不存在目标值,返回 [-1, -1]。 -# 示例 1: -# 输入: nums = [5,7,7,8,8,10], target = 8 -# 输出: [3,4] -# 示例 2: -# 输入: nums = [5,7,7,8,8,10], target = 6 -# 输出: [-1,-1] -# def searchRange(self, nums: List[int], target: int) -> List[int]: - - -# 思路:由于题目要求使用logN复杂度的算法, 所以这里使用二分搜索算法, -# 从基本的二分搜索的进行修改, 目前的算法还有优化的余地 - - -class Solution: - def searchRange(self, nums, target): - self.min = len(nums) - self.max = -1 - r = self.min - 1 - self.helper(nums, target, 0, r) - if self.min > self.max: - return [-1,-1] - return [self.min, self.max] - - def helper(self, nums, target, l, r): - if l <= r: - mid = int((l+r)/2) - if nums[mid] > target: - # print(nums[l:mid]) - self.helper(nums, target, l, mid-1) - elif nums[mid] < target: - # print(nums[mid+1:r]) - self.helper(nums, target, mid+1, r) - else: - self.max = max(mid, self.max) - self.min = min(mid, self.min) - self.helper(nums, target, l, mid-1) - self.helper(nums, target, mid + 1, r) diff --git "a/\350\247\204\345\276\213\351\242\230/35\346\220\234\347\264\242\346\217\222\345\205\245\344\275\215\347\275\256" "b/\350\247\204\345\276\213\351\242\230/35\346\220\234\347\264\242\346\217\222\345\205\245\344\275\215\347\275\256" deleted file mode 100644 index f245fc3..0000000 --- "a/\350\247\204\345\276\213\351\242\230/35\346\220\234\347\264\242\346\217\222\345\205\245\344\275\215\347\275\256" +++ /dev/null @@ -1,28 +0,0 @@ -# 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 -# 你可以假设数组中无重复元素。 -# 示例 1: -# 输入: [1,3,5,6], 5 -# 输出: 2 -# 示例 2: -# 输入: [1,3,5,6], 2 -# 输出: 1 -# 示例 3: -# 输入: [1,3,5,6], 7 -# 输出: 4 -# 示例 4: -# 输入: [1,3,5,6], 0 -# 输出: 0 -# def searchInsert(self, nums: List[int], target: int) -> int: - - -# 思路:这道题是典型的搜索, 由于没有特殊要求, 所以可以直接使用循环来解决 -# 如果想要降低时间复杂度, 可以使用二分搜索进行修改 - - -class Solution: - def searchInsert(self, nums, target): - res = -1 - for i in range(len(nums)): - if target > nums[i]: - res = i - return res + 1 diff --git "a/\350\247\204\345\276\213\351\242\230/49\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204" "b/\350\247\204\345\276\213\351\242\230/49\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204" deleted file mode 100644 index 8d21611..0000000 --- "a/\350\247\204\345\276\213\351\242\230/49\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215\345\210\206\347\273\204" +++ /dev/null @@ -1,27 +0,0 @@ -# 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。 -# 示例: -# 输入: ["eat", "tea", "tan", "ate", "nat", "bat"], -# 输出: -# [ -# ["ate","eat","tea"], -# ["nat","tan"], -# ["bat"] -# ] -# 说明: -# 所有输入均为小写字母。 -# 不考虑答案输出的顺序。 -# def groupAnagrams(self, strs: List[str]) -> List[List[str]]: - - -# 思路:这道题的具体思路有很多种, 包括使用素数来构成区别, 或者使用26的进制计算来构成区别, -# 或者是把乱序单词先排序等思路, 但是基本上都是使用字典储存+O(NK)的时间复杂度, 所以我将选用 -# 乱序单词先排序的思路(比较直接)来解答这个问题 -from collections import defaultdict - - -class Solution: - def groupAnagrams(self, strs): - dct = defaultdict(list) - for i in strs: - dct[''.join(sorted(i))].append(i) - return dct.values() diff --git "a/\350\247\204\345\276\213\351\242\230/50\346\261\202\345\271\202" "b/\350\247\204\345\276\213\351\242\230/50\346\261\202\345\271\202" deleted file mode 100644 index 6f5a79d..0000000 --- "a/\350\247\204\345\276\213\351\242\230/50\346\261\202\345\271\202" +++ /dev/null @@ -1,67 +0,0 @@ -# 实现 pow(x, n) ,即计算 x 的 n 次幂函数。 -# 示例 1: -# 输入: 2.00000, 10 -# 输出: 1024.00000 -# 示例 2: -# 输入: 2.10000, 3 -# 输出: 9.26100 -# 示例 3: -# 输入: 2.00000, -2 -# 输出: 0.25000 -# 解释: 2-2 = 1/22 = 1/4 = 0.25 -# 说明: -# -100.0 < x < 100.0 -# n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。 - - -# 思路:这里的暴力破解法就是模拟算术过程, 不过有更好的解决方案, 因为在幂计算的过程中 -# A3*A3 = A (3+3) 这样基于二分搜索可以减少计算过程, 可以加速计算过程 -# 并且使用二进制和动态规划的查找表思路来优化这个二分搜索思路, 击败95 -# 其实这里使用自顶而下的递归写法也是可以的,并且不需要记忆化搜索, 因为这里 -# 要计算的是上一个递归返回值的平方, 不像f(n) = f(n-1) + f(n-2)这种存在多层级 -# 的计算, 如果存在多层级的计算必须使用记忆化搜索, -# 但是由于需要的恰好是上一级返回值, 所以不需要记忆化搜索, 附上递归的写法 - - -class Solution: - def myPow(self, x, n): - if n == 0: - return 1 - if n == 1: - return x - if n == -1: - return 1 / x - sign = self.myPow(x, n%2) - if n < 0: - sign = 1/sign - half = self.myPow(x, int(n / 2)) - return sign * half * half - - -class Solution2: - def myPow(self, x, n): - if x == 0: - return 0 - if n == 0: - return 1 - k = abs(n) - str1 = str(bin(k))[2:] - dct = {'1': 1, '0': 0} - lst = [] - size = len(str1) - for i in range(1, size+1): - lst.append(dct[str1[-i]]) - # 制作查找表 - dp = [1] * size - dp[0] = abs(x) - for i in range(1, size): - dp[i] = dp[i-1] * dp[i-1] - res = 1 - for i in range(size): - if lst[i] == 1: - res = res * dp[i] - if x < 0 and lst[0] == 1: - res = - res - if n < 0: - res = 1 / res - return res diff --git "a/\350\247\204\345\276\213\351\242\230/58\346\234\200\345\220\216\344\270\200\344\270\252\345\215\225\350\257\215\347\232\204\351\225\277\345\272\246" "b/\350\247\204\345\276\213\351\242\230/58\346\234\200\345\220\216\344\270\200\344\270\252\345\215\225\350\257\215\347\232\204\351\225\277\345\272\246" deleted file mode 100644 index 895680f..0000000 --- "a/\350\247\204\345\276\213\351\242\230/58\346\234\200\345\220\216\344\270\200\344\270\252\345\215\225\350\257\215\347\232\204\351\225\277\345\272\246" +++ /dev/null @@ -1,25 +0,0 @@ -# 给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。 -# 如果不存在最后一个单词,请返回 0 。 -# 说明:一个单词是指由字母组成,但不包含任何空格的字符串。 -# 示例: -# 输入: "Hello World" -# 输出: 5 -# def lengthOfLastWord(self, s: str) -> int: - - -# 思路:从右往左数, 边数边记数, 遇到空格就停止记数 - - -class Solution: - def lengthOfLastWord(self, s): - size = len(s) - r = size - 1 - res = 0 - if s == '': - return 0 - while r >= 0 and s[r] == ' ': - r -= 1 - while r >= 0 and s[r] != ' ': - res += 1 - r -= 1 - return res diff --git "a/\350\247\204\345\276\213\351\242\230/60\345\233\236\346\272\257\347\232\204\347\254\254K\347\247\215\346\216\222\345\210\227" "b/\350\247\204\345\276\213\351\242\230/60\345\233\236\346\272\257\347\232\204\347\254\254K\347\247\215\346\216\222\345\210\227" deleted file mode 100644 index 1a477f1..0000000 --- "a/\350\247\204\345\276\213\351\242\230/60\345\233\236\346\272\257\347\232\204\347\254\254K\347\247\215\346\216\222\345\210\227" +++ /dev/null @@ -1,53 +0,0 @@ -# 给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。 -# 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: -# "123" -# "132" -# "213" -# "231" -# "312" -# "321" -# 给定 n 和 k,返回第 k 个排列。 -# 说明: -# 给定 n 的范围是 [1, 9]。 -# 给定 k 的范围是[1,  n!]。 -# 示例 1: -# 输入: n = 3, k = 3 -# 输出: "213" -# 示例 2: -# 输入: n = 4, k = 9 -# 输出: "2314" -# def getPermutation(self, n: int, k: int) -> str: - - -# 思路:明显可以使用回溯法边遍历边记数, -# 但是回溯明显没有规律厉害,所以写规律 - - -class Solution: - def getPermutation(self, n, k): - dp = [1] * 10 # 阶乘搜索表 - dp2 = [str(i) for i in range(10)] # 数字所用数组 - for i in range(1, n + 1): - dp[i] = dp[i - 1] * i - for i in range(1, 10): - if k <= dp[i]: - level = i - break - string = '' - real = 1 - for i in range(1, n - level + 1): - string += str(i) - real += 1 - rel = n - level + 1 - while level > 0: - total = -1 - while k > 0: - k = k - dp[level - 1] - total += 1 - k = k + dp[level - 1] - level -= 1 - string += dp2[rel + total] - dp2.insert(real, dp2.pop(rel + total)) - rel += 1 - real += 1 - return string diff --git "a/\350\247\204\345\276\213\351\242\230/66\345\212\240\344\270\200" "b/\350\247\204\345\276\213\351\242\230/66\345\212\240\344\270\200" deleted file mode 100644 index 53044e2..0000000 --- "a/\350\247\204\345\276\213\351\242\230/66\345\212\240\344\270\200" +++ /dev/null @@ -1,36 +0,0 @@ -# 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。 -# 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 -# 你可以假设除了整数 0 之外,这个整数不会以零开头。 -# 示例 1: -# 输入: [1,2,3] -# 输出: [1,2,4] -# 解释: 输入数组表示数字 123。 -# 示例 2: -# 输入: [4,3,2,1] -# 输出: [4,3,2,2] -# 解释: 输入数组表示数字 4321。 -# def plusOne(self, digits: List[int]) -> List[int]: - - -# 思路:把列表中的一个一个的整型组合成一个整型,然后+1 -# 主要在于组合成一个整型的思路, 从高位开始, 每次将高位*10即可 -# 并且要返回一个相似的列表 -# 我使用另一种思路, 从个位数开始, 不再需要进一的时候即可直接提交 -# 如果恰好99 +1 这种, 我在最后放置的一个判断是否需要进一 -# 由于不需要进一的数在循环过程中直接结束了, 所以循环过程结束还在运行的 -# 说明该数必须进一 - - -class Solution: - def plusOne(self, digits): - rec = 1 - for i in range(1, len(digits)+1): - temp = rec + digits[-i] - if temp > 9: - digits[-i] = temp - 10 - rec = 1 - else: - digits[-i] = temp - return digits - digits.insert(0, 1) - return digits diff --git "a/\350\247\204\345\276\213\351\242\230/67\344\272\214\350\277\233\345\210\266\345\255\227\347\254\246\344\270\262\346\261\202\345\222\214" "b/\350\247\204\345\276\213\351\242\230/67\344\272\214\350\277\233\345\210\266\345\255\227\347\254\246\344\270\262\346\261\202\345\222\214" deleted file mode 100644 index 7b2b8f3..0000000 --- "a/\350\247\204\345\276\213\351\242\230/67\344\272\214\350\277\233\345\210\266\345\255\227\347\254\246\344\270\262\346\261\202\345\222\214" +++ /dev/null @@ -1,33 +0,0 @@ -# 给定两个二进制字符串,返回他们的和(用二进制表示)。 -# 输入为非空字符串且只包含数字 1 和 0。 -# 示例 1: -# 输入: a = "11", b = "1" -# 输出: "100" -# 示例 2: -# 输入: a = "1010", b = "1011" -# 输出: "10101" -# def addBinary(self, a: str, b: str) -> str: - - -# 思路:由于最后要返回的是二进制形式的字符串, 所以可以不需要进行二进制和 -# 十进制的转换, 所以我将制作一个字典进行转换 - - -class Solution: - def addBinary(self, a, b): - dct = {'0': 0, '1': 1, 0: ('0', 0), 1: ('1', 0), 2: ('0', 1), 3: ('1', 1)} - size1 = len(a) - size2 = len(b) - if size1 < size2: - a = '0' * (size2 - size1) + a - else: - b = '0' * (size1 - size2) + b - lst = ['0'] - rec = 0 - for i in range(1, len(a)+1): - temp, rec = dct[dct[a[-i]] + rec + dct[b[-i]]] - lst.insert(0, temp) - lst.pop() - if rec: - lst.insert(0, '1') - return ''.join(lst) diff --git "a/\350\247\204\345\276\213\351\242\230/6Z\345\255\227\345\275\242\345\217\230\346\215\242" "b/\350\247\204\345\276\213\351\242\230/6Z\345\255\227\345\275\242\345\217\230\346\215\242" deleted file mode 100644 index 5789a7b..0000000 --- "a/\350\247\204\345\276\213\351\242\230/6Z\345\255\227\345\275\242\345\217\230\346\215\242" +++ /dev/null @@ -1,45 +0,0 @@ -# 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。 -# 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: -# L C I R -# E T O E S I I G -# E D H N -# 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。 -# 请你实现这个将字符串进行指定行数变换的函数: -# string convert(string s, int numRows); -# 示例 1: -# 输入: s = "LEETCODEISHIRING", numRows = 3 -# 输出: "LCIRETOESIIGEDHN" -# 示例 2: -# 输入: s = "LEETCODEISHIRING", numRows = 4 -# 输出: "LDREOEIIECIHNTSG" -# 解释: -# L D R -# E O E I I -# E C I H N -# T S G -# def convert(self, s: str, numRows: int) -> str: - - -# 思路:这道题明显是一道规律题, 重点在于找到删除字符串的规律 -# 明显给出的字符串将按照给定的行数设置, 以Z字形进行排列 -# 这里可以使用列表的功能, 在列表内创建要求数目的空字符串, 然后 -# 按照规律, 把对应位置的字符串增加到对应的字符串中, 最后把所有字符串合起来 - - -class Solution: - def convert(self, s, numRows): - if numRows == 1: - return s - lst = ['' for i in range(numRows)] - curRow = 0 - turn = False - for i in s: - lst[curRow] += i - if curRow == 0 or curRow == numRows - 1: - turn = not turn - if turn: - curRow += 1 - else: - curRow -= 1 - res = ''.join(lst) - return res diff --git "a/\350\247\204\345\276\213\351\242\230/75\351\242\234\350\211\262\345\210\206\347\261\273" "b/\350\247\204\345\276\213\351\242\230/75\351\242\234\350\211\262\345\210\206\347\261\273" deleted file mode 100644 index 9013db6..0000000 --- "a/\350\247\204\345\276\213\351\242\230/75\351\242\234\350\211\262\345\210\206\347\261\273" +++ /dev/null @@ -1,37 +0,0 @@ -# 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 -# 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 -# 注意: -# 不能使用代码库中的排序函数来解决这道题。 -# 示例: -# 输入: [2,0,2,1,1,0] -# 输出: [0,0,1,1,2,2] -# 进阶: -# 一个直观的解决方案是使用计数排序的两趟扫描算法。 -# 首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。 -# 你能想出一个仅使用常数空间的一趟扫描算法吗? -# def sortColors(self, nums: List[int]) -> None: - - -# 思路:这题是典型的使用单次快排思路的题目, 使用三指针 -# l(left), mid, r(right)指针来操作 -# 首先l处于最左端, mid和l重合, r处于最右段, 左闭右闭 -# 如果mid所在值 < 0,mid右移, l右移, 如果 == 1, mid右移 -# 如果 > 1, mid和r交换值, r左移, 终止条件是mid > r -# 注意指针l和r所在位置其实都不属于左右两侧的 - - -class Solution: - def sortColors(self, nums): - l = mid = 0 - r = len(nums) - 1 - while mid <= r: - if nums[mid] > 1: - nums[mid], nums[r] = nums[r], nums[mid] - r -= 1 - elif nums[mid] < 1: - nums[mid], nums[l] = nums[l], nums[mid] - mid += 1 - l += 1 - else: - mid += 1 - return diff --git "a/\350\247\204\345\276\213\351\242\230/7\346\225\264\346\225\260\345\217\215\350\275\254" "b/\350\247\204\345\276\213\351\242\230/7\346\225\264\346\225\260\345\217\215\350\275\254" deleted file mode 100644 index 0288880..0000000 --- "a/\350\247\204\345\276\213\351\242\230/7\346\225\264\346\225\260\345\217\215\350\275\254" +++ /dev/null @@ -1,34 +0,0 @@ -# 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 -# 示例 1: -# 输入: 123 -# 输出: 321 -#  示例 2: -# 输入: -123 -# 输出: -321 -# 示例 3: -# 输入: 120 -# 输出: 21 -# def reverse(self, x: int) -> int: - - -# 思路:从右往左获取所有数字, 然后从左往右构建新整型 -# 由于leetcode的环境不能储存超过32位的有符号整数, 增加一个判断 - - -class Solution: - def reverse(self, x): - if x == 0: - return 0 - sign = 1 - if x < 0: - sign = -1 - x = -x - res = 0 - while x >= 10: - y = x % 10 - x = x // 10 - res = y + res * 10 - res = (x + res * 10) * sign - if -2147483648 > res or 2147483647 < res: - return 0 - return res diff --git "a/\350\247\204\345\276\213\351\242\230/8\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\225\264\346\225\260" "b/\350\247\204\345\276\213\351\242\230/8\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\225\264\346\225\260" deleted file mode 100644 index 1aa6bad..0000000 --- "a/\350\247\204\345\276\213\351\242\230/8\345\255\227\347\254\246\344\270\262\350\275\254\346\215\242\346\225\264\346\225\260" +++ /dev/null @@ -1,72 +0,0 @@ -# 请你来实现一个 atoi 函数,使其能将字符串转换成整数。 -# 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 -# 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。 -# 该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。 -# 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。 -# 在任何情况下,若函数不能进行有效的转换时,请返回 0。 -# 说明: -# 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231,  231 − 1]。如果数值超过这个范围,请返回  INT_MAX (231 − 1) 或 INT_MIN (−231) 。 -# 示例 1: -# 输入: "42" -# 输出: 42 -# 示例 2: -# 输入: " -42" -# 输出: -42 -# 解释: 第一个非空白字符为 '-', 它是一个负号。 -#   我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。 -# 示例 3: -# 输入: "4193 with words" -# 输出: 4193 -# 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。 -# 示例 4: -# 输入: "words and 987" -# 输出: 0 -# 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。 -# 因此无法执行有效的转换。 -# 示例 5: -# 输入: "-91283472332" -# 输出: -2147483648 -# 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 -#   因此返回 INT_MIN (−231) 。 -# def myAtoi(self, str: str) -> int: - - -# 思路:先把左侧空格内容去除, 然后判断是否符合是负号或数字的字符串, -# 如果不是直接停止, 把符号和数字分别放到两个变量中, 最后进行乘法 - - -class Solution: - def myAtoi(self, str): - dct = {'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0} - sign = 1 - k = 0 - for i in str: - if i != ' ': - break - k += 1 - str2 = str[k:] - if str2 == '': - return 0 - if str2[0] not in dct and str2[0] != '-' and str2[0] != '+': - return 0 - if str2[0] == '-': - sign = -1 - str2 = str2[1:] - elif str2[0] == '+': - str2 = str2[1:] - lst = [] - for i in str2: - if i not in dct: - break - lst.append(i) - size = len(lst) - if size == 0: - return 0 - rec = 0 - for i in range(0, size): - rec = 10 * rec + dct[lst[i]] - if rec >= 2147483648: - if sign == 1: - return 2147483647 - return -2147483648 - return sign * rec diff --git "a/\350\247\204\345\276\213\351\242\230/9\345\233\236\346\226\207\346\225\260" "b/\350\247\204\345\276\213\351\242\230/9\345\233\236\346\226\207\346\225\260" deleted file mode 100644 index 20d1251..0000000 --- "a/\350\247\204\345\276\213\351\242\230/9\345\233\236\346\226\207\346\225\260" +++ /dev/null @@ -1,37 +0,0 @@ -# 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 -# 示例 1: -# 输入: 121 -# 输出: true -# 示例 2: -# 输入: -121 -# 输出: false -# 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 -# 示例 3: -# 输入: 10 -# 输出: false -# 解释: 从右向左读, 为 01 。因此它不是一个回文数。 -# 进阶: -# 你能不将整数转为字符串来解决这个问题吗? -# def isPalindrome(self, x: int) -> bool: - - -# 思路:如果给定的是一个字符串的话那直接求半数, 然后分别从左右两侧往中间 -# 遍历, 检查是否完全一致即可, 但是题目希望我们不要转换成字符串 -# 我们可以通过取商和取余来达到两侧往中间移动的目的 -# 也可以通过整数反转后对比原来的数判断是否相等来证明回文数 - - -class Solution: - def isPalindrome(self, x): - if x < 0: - return False - if x < 10: - return True - res = 0 - z = x - while x >= 10: - y = x % 10 - x = x // 10 - res = y + res * 10 - res = x + res * 10 - return res == z diff --git "a/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/26\345\216\237\345\234\260\345\210\240\351\231\244\346\225\260\347\273\204\344\270\255\351\207\215\345\244\215\347\232\204\345\200\274" "b/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/26\345\216\237\345\234\260\345\210\240\351\231\244\346\225\260\347\273\204\344\270\255\351\207\215\345\244\215\347\232\204\345\200\274" deleted file mode 100644 index 6a178a5..0000000 --- "a/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/26\345\216\237\345\234\260\345\210\240\351\231\244\346\225\260\347\273\204\344\270\255\351\207\215\345\244\215\347\232\204\345\200\274" +++ /dev/null @@ -1,41 +0,0 @@ -# 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 -# 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 -# 示例 1: -# 给定数组 nums = [1,1,2], -# 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 -# 你不需要考虑数组中超出新长度后面的元素。 -# 示例 2: -# 给定 nums = [0,0,1,1,1,2,2,3,3,4], -# 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 -# 你不需要考虑数组中超出新长度后面的元素。 -# 说明: -# 为什么返回数值是整数,但输出的答案是数组呢? -# 请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 -# def removeDuplicates(self, nums: List[int]) -> int: - - -# 思路:明显的这里要进行原地删除, 所以就是使用偷天换日的手法, 把后一个数的值 -# 搬到当前值来, 从而使得该数组的前一部分是没有重复元素的 -# 对于处理重复值的方法, 可以使用双指针来找到一个合适放置位置 -# 使用慢指针从索引0开始, 如果快指针遇到的值和慢指针的值不同, 说明这个值是应该被归入答案的 -# 如果是相同的, 说明这个值应该被闲置, 直接跳过这部分([i+1, j]这部分是用来放置闲置的值的) -# 等到遇到不同的值, 就把这个值和慢指针的下一个位置交换, 然后把慢指针前移一个 -# 这样到慢指针所在的索引部分都是正确的值 -# 或者从另一个角度去理解 -# 使用r(快指针)在慢指针前一格开始遍历, 如果快指针和慢指针l是相同的值, 说明快指针所在的值应该 -# 被换走, 但是还没有找到合适交换的位置, 所以先不管, 快指针继续往前走,指导遇到的值 -# 和慢指针的值不同就说明当前快指针所在的值应该就是属于正确答案的一部分, 也是刚才被标记 -# 的应该被换掉的值(l+1的格)应该被放置的位置, 把值交换之后, 把慢指针前移一格, 继续重复刚才的操作 -# l所在的位置就是没有重复元素的最后一个位置 -# 注意:题目要的数值, 是l指针所在索引+1 - - -class Solution: - def removeDuplicates(self, nums): - size = len(nums) - i = 0 - for j in range(1, size): - if nums[i] != nums[j]: - nums[i + 1], nums[j] = nums[j], nums[i + 1] - i += 1 - return i + 1 diff --git "a/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/\344\274\230\351\233\205\347\232\204\346\214\207\351\222\21088\345\216\237\345\234\260\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204" "b/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/\344\274\230\351\233\205\347\232\204\346\214\207\351\222\21088\345\216\237\345\234\260\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204" deleted file mode 100644 index 47a9e21..0000000 --- "a/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/\344\274\230\351\233\205\347\232\204\346\214\207\351\222\21088\345\216\237\345\234\260\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204" +++ /dev/null @@ -1,37 +0,0 @@ -# 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。 -# 说明: -# 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 -# 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。 -# 示例: -# 输入: -# nums1 = [1,2,3,0,0,0], m = 3 -# nums2 = [2,5,6], n = 3 -# 输出: [1,2,2,3,5,6] -# def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: - - -# 思路:对两个有序数组进行合并其实并不难, 但是这里要求进行原地排序 -# 当然即使要求原地排序也不难, 但是考虑想用比较优的方法来解答, -# 这里将使用三指针来进行排序, 两个指针分别指向两个数组要比较的位置(从右往左) -# 第三个指针指向将要被填充的位置(最开始就是m+n-1索引的位置) -# 偏大的值将会填充到第三个指针的位置, 然后第三个指针向前移动直至到索引0 - - -class Solution: - def merge(self, nums1, m, nums2, n): - move = m + n - 1 - m -= 1 - n -= 1 - while m > -1 and n > -1: - if nums1[m] >= nums2[n]: - nums1[move] = nums1[m] - m -= 1 - else: - nums1[move] = nums2[n] - n -= 1 - move -= 1 - if n != -1: - for i in range(move, -1, -1): - nums1[i] = nums2[n] - n -= 1 - return diff --git "a/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/\350\277\233\345\210\266\346\234\211\345\205\26329\344\270\244\346\225\260\347\233\270\351\231\244" "b/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/\350\277\233\345\210\266\346\234\211\345\205\26329\344\270\244\346\225\260\347\233\270\351\231\244" deleted file mode 100644 index a80300f..0000000 --- "a/\350\247\204\345\276\213\351\242\230/\345\200\274\345\276\227\345\205\263\346\263\250\347\232\204\346\212\200\345\267\247\351\242\230/\350\277\233\345\210\266\346\234\211\345\205\26329\344\270\244\346\225\260\347\233\270\351\231\244" +++ /dev/null @@ -1,108 +0,0 @@ -# 给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。 -# 返回被除数 dividend 除以除数 divisor 得到的商。 -# 示例 1: -# 输入: dividend = 10, divisor = 3 -# 输出: 3 -# 示例 2: -# 输入: dividend = 7, divisor = -3 -# 输出: -2 -# 说明: -# 被除数和除数均为 32 位有符号整数。 -# 除数不为 0。 -# 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231,  231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。 -# def divide(self, dividend: int, divisor: int) -> int: - - -# 思路:这个题目跟进制很有关系, 试想, 对于一个二进制表达而言 -# 一个数除以2的结果, 其实就是舍弃二进制最后一位后得到的数, -# 所以我制作一个除数进制的表(反向的)因为反向的列表不需要一直修改列表的索引值 -# 比如制作一个三进制表[1, 3, 9, 27, 81, 243], 是反向的表, 目标值为180, 根据三进制表算出180的三进制数值为 20200 -# 0 0 2 0 2 -# 由于在对应进制中想要把一个数除以N倍, 只需要把他在对应的进制数中后移一位即可 -# 0 0 2 0 2 -# 由于除以3等于把最后一位舍去, 所以得到的答案是2020(三进制)再转换回十进制 -# [3, 9, 27, 81, 243] -# 2 0 2(这是正向的第一个2) == 3 + 3 + 27 + 27 = 60 -# 同样的思路, 做成二进制表也是可以的(并且由于案例中可能存在被除数十分大的 -# 情况, 这样制作一个以被除数决定进制的函数用起来是没有意义的, 所以制作二进制表 -# 已知标准的二进制表应该是以一为首位进行延伸的, 如果我们以被除数为首位进行延伸, 即可构建 -# 一个用来除以被除数的二进制表 -# [1, 2, 4, 8, 16, 32, 64, 128] 下面将以被除数为3为例 -# [3, 6, 12,24,48, 96, 192,384] 仔细观察可以发现, 上面的表对应索引的值的3倍就是下面的值 -# 所以可以通过构建类二进制表(用来计算)和二进制表(用来参考计商) -# 以达到对商很大的除法达到快速计算的效果 - - -# 二进制表 -class Solution: - def divide(self, dividend, divisor): - if (dividend > 0 and divisor > 0) or (dividend < 0 and divisor < 0): - sign = 1 - else: - sign = -1 - dividend = abs(dividend) - divisor = abs(divisor) - if dividend < divisor: - return 0 - lst = [] - # 构建类二进制表, 表内每一个数值恰好是二进制中数值的被除数倍 - for i in range(dividend): - if divisor > dividend: - break - lst.append(divisor) - divisor = divisor + divisor - size = len(lst) - # 构建二进制表 - dp = [1] * size - for i in range(1, size): - dp[i] = dp[i-1] + dp[i-1] - res = 0 - for i in range(size-1, -1, -1): - total = dividend - lst[i] - if total > 0: - res += dp[i] - dividend = total - if dividend == lst[0]: - res += 1 - if sign < 0: - return -min(res, 2147483648) - return min(res, 2147483647) - - -# 被除数进制表 -class Solution: - def divide(self, dividend: int, divisor: int) -> int: - sign = -1 - if (dividend > 0 and divisor > 0) or (dividend < 0 and divisor < 0): - sign = 1 - dividend = abs(dividend) - divisor = abs(divisor) - if divisor == 1: - res = dividend - elif divisor > dividend: - res = 0 - elif divisor == dividend: - res = 1 - else: - dp = [divisor] - n = divisor - for i in range(dividend + 2): - rec = 0 - for j in range(divisor): - rec += n - n = rec - dp.append(n) - if n > dividend: - break - print(dp) - res = 0 - for i in range(1, len(dp)): - while dividend >= dp[-i]: - res += dp[-i - 1] - dividend -= dp[-i] - while dividend >= dp[0]: - res += 1 - dividend -= dp[0] - if sign < 0: - return -min(res, 2147483648) - return min(res, 2147483647) diff --git "a/\350\247\204\345\276\213\351\242\230/\347\211\271\346\256\212\344\272\214\345\210\206\346\220\234\347\264\24233\346\220\234\347\264\242\346\227\213\350\275\254\346\225\260\347\273\204" "b/\350\247\204\345\276\213\351\242\230/\347\211\271\346\256\212\344\272\214\345\210\206\346\220\234\347\264\24233\346\220\234\347\264\242\346\227\213\350\275\254\346\225\260\347\273\204" deleted file mode 100644 index c5b3453..0000000 --- "a/\350\247\204\345\276\213\351\242\230/\347\211\271\346\256\212\344\272\214\345\210\206\346\220\234\347\264\24233\346\220\234\347\264\242\346\227\213\350\275\254\346\225\260\347\273\204" +++ /dev/null @@ -1,69 +0,0 @@ -# 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 -# ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。 -# 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。 -# 你可以假设数组中不存在重复的元素。 -# 你的算法时间复杂度必须是 O(log n) 级别。 -# 示例 1: -# 输入: nums = [4,5,6,7,0,1,2], target = 0 -# 输出: 4 -# 示例 2: -# 输入: nums = [4,5,6,7,0,1,2], target = 3 -# 输出: -1 -# def search(self, nums: List[int], target: int) -> int: - - -# 思路:由于题目要求时间复杂度logN, 所以很大可能是使用二分搜索了 -# 接下来分析一下这个被旋转过后的有序数组的特点:1)首位l应该比末位r大 -# 2)如果以二分搜索的操作来尝试, 查找旋转后的数组的中值, 判断中值如果大于r的值,说明 -# 旋转点在右侧, 如果大于l的值, 说明旋转点在左侧, 接下来判断 -# 找的值是大于首位小于中值还是……将获得下一个更小的范围, 递归进行上面的那种二分搜索, 直至符合终止条件 -# 虽然写起来很长, 但是击败98.96, 还可以 - - -class Solution: - def search(self, nums, target): - if nums == []: - return -1 - size = len(nums) - return self.binarysearch(nums, 0, size - 1, target) - - def binarysearch(self, nums, l, r, target): # [l, r]左闭右闭, 特殊二分搜索 - if r - l < 2: # 如果元素个数少于3个直接遍历 - for i in range(l, r + 1): - if nums[i] == target: - return i - return -1 - mid = int((l + r) / 2) # 中间偏右 - if nums[mid] == target: - return mid - if nums[l] == target: - return l - if nums[mid] > nums[l]: # 旋转点在右侧 - if target > nums[mid]: - return self.binarysearch(nums, mid + 1, r, target) - else: - if target >= nums[l]: - return self.helper(nums, l, mid - 1, target) - else: - return self.binarysearch(nums, mid + 1, r, target) - else: # 旋转点在左侧 - if target > nums[mid]: - if target <= nums[l]: - return self.helper(nums, mid + 1, r, target) - else: - return self.binarysearch(nums, l, mid - 1, target) - else: - return self.binarysearch(nums, l, mid - 1, target) - - def helper(self, nums, l, r, target): # 普通二分搜索 - if l > r: - return -1 - if l == r and target == nums: - return l - mid = int((l + r) / 2) - if nums[mid] == target: - return mid - elif nums[mid] < target: - return self.helper(nums, mid + 1, r, target) - else: - return self.helper(nums, l, mid - 1, target) diff --git "a/\351\223\276\350\241\250/109\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254AVL" "b/\351\223\276\350\241\250/109\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254AVL" deleted file mode 100644 index 86ab190..0000000 --- "a/\351\223\276\350\241\250/109\346\234\211\345\272\217\351\223\276\350\241\250\350\275\254AVL" +++ /dev/null @@ -1,48 +0,0 @@ -# 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。 -# 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。 -# 示例: -# 给定的有序链表: [-10, -3, 0, 5, 9], -# 一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树: -# 0 -# / \ -# -3 9 -# / / -# -10 5 -# def sortedListToBST(self, head: ListNode) -> TreeNode: - - -# 思路:从一般解法上来说, 有序固然跟二叉搜索树是天然契合的, 但是由于链表无法随机访问 -# 导致直接的寻找中值建二叉树变得困难, 这算是链表的特性带来的一个比较重要的不足 -# 解法有很多, 比如先寻找整段链表的中值节点, 把链表分成左右两个链表, 中值做成根节点 -# 然后递归寻找中值节点, 递归建树 -# 但是很明显树用的节点和链表用的节点结构是不一样的, -# 所以其实还是在于值的传递 -# 如果是链表的节点传递当然最好是避免使用列表(与作弊无异), -# 但是这明显是一个传递值构建树的过程, 换言之用链表也是为了传递值, -# 所以强行保持链表属性毫无意义, 所以我选用列表来解答 -# 与其多次重复在链表上移动获取值, 不如直接一次获取所有值并存入列表中来得方便 - - -class Solution: - def sortedListToBST(self, head): - if head == None: - return - lst = [] - # 把值存入列表 - while head != None: - lst.append(head.val) - head = head.next - size = len(lst) - # 递归建树 - node = self.betree(0, size - 1, lst) - return node - - def betree(self, l, r, lst): - # 跟二分搜索很相似 - if l > r: - return - mid = int((l + r) / 2) - node = TreeNode(lst[mid]) - node.left = self.betree(l, mid - 1, lst) - node.right = self.betree(mid + 1, r, lst) - return node diff --git "a/\351\223\276\350\241\250/203\345\201\267\345\244\251\346\215\242\346\227\245" "b/\351\223\276\350\241\250/203\345\201\267\345\244\251\346\215\242\346\227\245" deleted file mode 100644 index 256419f..0000000 --- "a/\351\223\276\350\241\250/203\345\201\267\345\244\251\346\215\242\346\227\245" +++ /dev/null @@ -1,31 +0,0 @@ -# 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。 -# 现有一个链表 -- head = [4,5,1,9],它可以表示为: -# 示例 1: -# 输入: head = [4,5,1,9], node = 5 -# 输出: [4,1,9] -# 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. -# 示例 2: -# 输入: head = [4,5,1,9], node = 1 -# 输出: [4,5,9] -# 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9. -# 说明: -# 链表至少包含两个节点。 -# 链表中所有节点的值都是唯一的。 -# 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 -# 不要从你的函数中返回任何结果。 -# def deleteNode(self, node): - - -# 思路:这道题和203的移除链表中值为某个定值的节点的情况很像, 但是这里要求的是直接删除 -# 当前节点, 这和我82题写的一个判断自己这个节点是否应该保留的函数的目的是一致的, -# 正常情况下只需要稍稍改写82的辅助函数就足够了 -# 却发现题目不传入链表的头节点给我们, 并且不允许返回, 其实是一条脑筋急转弯题, -# 我们把下一个节点的值抄到当前节点, 并把下一个节点去掉, -# 这样当前节点就变成了下一节点了(偷天换日) - - -class Solution: - def deleteNode(self, node): - # 由于题目提示这个节点一定不是末尾节点, 所以这个节点的下一个节点一定不为空, 不需要判断 - node.val = node.next.val - node.next = node.next.next diff --git "a/\351\223\276\350\241\250/23\345\220\210\345\271\266K\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250" "b/\351\223\276\350\241\250/23\345\220\210\345\271\266K\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250" deleted file mode 100644 index 9c85790..0000000 --- "a/\351\223\276\350\241\250/23\345\220\210\345\271\266K\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250" +++ /dev/null @@ -1,71 +0,0 @@ -# 合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 -# 示例: -# 输入: -# [ -#   1->4->5, -#   1->3->4, -#   2->6 -# ] -# 输出: 1->1->2->3->4->4->5->6 -# def mergeKLists(self, lists: List[ListNode]) -> ListNode: - - -# 思路:直接的思路可以使用暴力破解,但是考虑到每次都对比K个数值实在麻烦 -# 可以考虑使用最小堆,每次推出的内容中包含所在链表信息,然后推入对应链表的下一个数值(指针向后一格) -# 但是我比较喜欢使用类似计数排序的思路, 这里将使用计数排序进行解答 -# 后来发现要提交的是一个链表,感觉新建节点可能消耗过大,附上使用最小堆的解法 - - -class Solution: - def mergeKLists(self, lists): - maxval = 0 - minval = 0 - dict0 = {} - cur = pre = ListNode(None) - for i in lists: - while i != None: - if i.val > maxval: - maxval = i.val - if i.val < minval: - minval = i.val - if i.val not in dict0: - dict0[i.val] = 1 - else: - dict0[i.val] += 1 - i = i.next - for i in range(minval, maxval+1): - if i not in dict0: - pass - elif dict0[i] == 1: - cur.next = ListNode(i) - cur = cur.next - else: - for j in range(dict0[i]): - cur.next = ListNode(i) - cur = cur.next - return pre.next - - -import heapq - - -class Solution: - def mergeKLists(self, lists): - if lists == []: - return None - pre = dummyhead = ListNode(None) - size = len(lists) - # visited = [0] * size - q = [] - size = len(lists) - for i in range(size): - if lists[i] != None: - heapq.heappush((lists[i].val, i)) - while len(q) > 0: - i, j = heapq.heappop(q) - pre.next = lists[j] - pre = pre.next - lists[j] = lists[j].next - if lists[j] != None: - heapq.heappush((lists[j].val, j)) - return dummyhead.next diff --git "a/\351\223\276\350\241\250/328\345\245\207\345\201\266\351\223\276\350\241\250(\346\230\223\346\203\263\351\232\276\345\206\231)" "b/\351\223\276\350\241\250/328\345\245\207\345\201\266\351\223\276\350\241\250(\346\230\223\346\203\263\351\232\276\345\206\231)" deleted file mode 100644 index 358731e..0000000 --- "a/\351\223\276\350\241\250/328\345\245\207\345\201\266\351\223\276\350\241\250(\346\230\223\346\203\263\351\232\276\345\206\231)" +++ /dev/null @@ -1,38 +0,0 @@ -# 给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。 -# 请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。 -# 示例 1: -# 输入: 1->2->3->4->5->NULL -# 输出: 1->3->5->2->4->NULL -# 示例 2: -# 输入: 2->1->3->5->6->4->7->NULL -# 输出: 2->3->6->7->1->5->4->NULL -# 说明: -# 应当保持奇数节点和偶数节点的相对顺序。 -# 链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。 -# def oddEvenList(self, head: ListNode) -> ListNode: - - -# 思路:由于需要把链表先分成两份, 再把两个链表合一,所以需要注意先判断前面的节点是否为None,不为None才接上 -#加上双指针 -# 注意:思路是挺简单的, 但是需要考虑很多情况,建议写法围绕着移动的head和head.next来写 -# 会比较好写 - - -class Solution: - def oddEvenList(self, head): - cur1 = pre1 = ListNode(None) - cur2 = pre2 = ListNode(None) - while head != None and head.next != None: - cur1.next = head - cur2.next = head.next - cur1 = cur1.next - cur2 = cur2.next - head = cur2.next - if head != None: - cur1.next = head - cur1 = cur1.next - cur2.next = None - cur1.next = pre2.next - return pre1.next - - diff --git "a/\351\223\276\350\241\250/445\344\270\244\346\225\260\347\233\270\345\212\240\351\253\230\344\275\215\345\244\264\347\273\223\347\202\271\347\211\210(\345\200\237\347\224\250\346\240\210)" "b/\351\223\276\350\241\250/445\344\270\244\346\225\260\347\233\270\345\212\240\351\253\230\344\275\215\345\244\264\347\273\223\347\202\271\347\211\210(\345\200\237\347\224\250\346\240\210)" deleted file mode 100644 index 2e3959e..0000000 --- "a/\351\223\276\350\241\250/445\344\270\244\346\225\260\347\233\270\345\212\240\351\253\230\344\275\215\345\244\264\347\273\223\347\202\271\347\211\210(\345\200\237\347\224\250\346\240\210)" +++ /dev/null @@ -1,52 +0,0 @@ -# 给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。 -# 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 -# 进阶: -# 如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。 -# 示例: -# 输入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) -# 输出: 7 -> 8 -> 0 -> 7 -# def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: - - -# 思路:这道题的概念和2题的两数相加几乎是一模一样的, 但是由于他的链表表示方式 -# 和我们的数字表示方式方向一直, 但是数学上运算都是从低位开始的,无法从高位开始 -# 建议先把列表整个翻转, 然后用2题的两数相加方案来解答 -# 但是由于进阶要求我们不能修改链表, 所以这种方法就不能使用 -# 那么可以使用栈来记录, 以解决错位问题, 并且写起来会更加简单 -from queue import LifoQueue - - -class Solution: - def addTwoNumbers(self, l1, l2): - p = LifoQueue() - q = LifoQueue() - self.l = LifoQueue() - while l1 != None: - p.put(l1.val) - l1 = l1.next - while l2 != None: - q.put(l2.val) - l2 = l2.next - rec = 0 - while not p.empty() and not q.empty(): - rec = self.helper(p.get(), q.get(), rec) - while not p.empty(): - rec = self.helper(p.get(), 0, rec) - while not q.empty(): - rec = self.helper(0, q.get(), rec) - cur = pre = ListNode(None) - if rec != 0: - cur.next = ListNode(1) - cur = cur.next - while not self.l.empty(): - cur.next = ListNode(self.l.get()) - cur = cur.next - return pre.next - - def helper(self, n1, n2, rec): - res = n1 + n2 + rec - if res > 9: - self.l.put(res%10) - return 1 - self.l.put(res) - return 0 diff --git "a/\351\223\276\350\241\250/725\345\210\206\351\232\224\351\223\276\350\241\250" "b/\351\223\276\350\241\250/725\345\210\206\351\232\224\351\223\276\350\241\250" deleted file mode 100644 index 8f6e87f..0000000 --- "a/\351\223\276\350\241\250/725\345\210\206\351\232\224\351\223\276\350\241\250" +++ /dev/null @@ -1,69 +0,0 @@ -# 给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分。 -# 每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null。 -# 这k个部分应该按照在链表中出现的顺序进行输出,并且排在前面的部分的长度应该大于或等于后面的长度。 -# 返回一个符合上述规则的链表的列表。 -# 举例: 1->2->3->4, k = 5 // 5 结果 [ [1], [2], [3], [4], null ] -# 示例 1: -# 输入: -# root = [1, 2, 3], k = 5 -# 输出: [[1],[2],[3],[],[]] -# 解释: -# 输入输出各部分都应该是链表,而不是数组。 -# 例如, 输入的结点 root 的 val= 1, root.next.val = 2, \root.next.next.val = 3, 且 root.next.next.next = null。 -# 第一个输出 output[0] 是 output[0].val = 1, output[0].next = null。 -# 最后一个元素 output[4] 为 null, 它代表了最后一个部分为空链表。 -# 示例 2: -# 输入: -# root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3 -# 输出: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]] -# 解释: -# 输入被分成了几个连续的部分,并且每部分的长度相差不超过1.前面部分的长度大于等于后面部分的长度。 -# 提示: -# root 的长度范围: [0, 1000]. -# 输入的每个节点的大小范围:[0, 999]. -# k 的取值范围: [1, 50]. -# def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]: - - -# 思路:先找出链表的size, 再用除法求出每段链表的节点数, 收集链表头, 使用迭代的方法写 - - -class Solution: - def splitListToParts(self, root, k): - if root == None: - return [] - lst = [] - pre = ListNode(None) - pre.next = root - cur = root - num = 0 - while cur != None: - num += 1 - cur = cur.next - if num <= k: - l = 0 # 每段的基础节点数,共有k段 - r = num # 如果节点总数不能被均分, 则前r段的节点数应该都是l+1 - else: - r = num % k - l = int(num / k) - cur = pre - while k > 0: - if r > 0: - ll = l + 1 - else: - ll = l - if ll == 0: - lst.append(None) - k -= 1 - continue - lst.append(cur.next) - while ll > 0: - cur = cur.next - ll -= 1 - head = cur.next - cur.next = None - cur = ListNode(None) - cur.next = head - r -= 1 - k -= 1 - return lst diff --git "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/143\351\207\215\346\216\222\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/143\351\207\215\346\216\222\351\223\276\350\241\250" deleted file mode 100644 index 9a7cd0f..0000000 --- "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/143\351\207\215\346\216\222\351\223\276\350\241\250" +++ /dev/null @@ -1,61 +0,0 @@ -# 给定一个单链表 L:L0→L1→…→Ln-1→Ln , -# 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… -# 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 -# 示例 1: -# 给定链表 1->2->3->4, 重新排列为 1->4->2->3. -# 示例 2: -# 给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3. -# def reorderList(self, head: ListNode) -> None: - - -# 思路:这基本算是遇到过的链表类题目中最困难的一题了, 不可以只改变值(这是当然的) -# 还需要部分反向的插入链表, 尤其是最后要求不返回内容, 也就是说检验的是本来的链表 -# 这说明这道题目要求原地修改 -# 其实解法也不难,而且很好想出来, 只是之前的两种思路的组合而已 -# 先跑到中间节点, 然后内部翻转后半段链表, 然后分别从两条链表开始, 间隔插入节点 - - -class Solution: - def reorderList(self, head): - if head == None or head.next == None: - return head - # 寻找中间节点 - slow = fast = pre = ListNode(None) - pre.next = head - while fast != None: - fast = fast.next - if fast == None: - break - fast = fast.next - slow = slow.next - # 切断并内部翻转后段链表 - pre2 = ListNode(None) - pre2.next = slow.next - slow.next = None - h1 = None - h2 = pre2.next - h3 = h2.next - while h3 != None: # 这里用h3来判断是为了减少while内部的判断次数 - h2.next = h1 - h1 = h2 - h2 = h3 - h3 = h2.next - # 由于上面用的是h3来判断, 所以内部是不需要判断的, 但这会导致并没有翻转完, 差一次 - h2.next = h1 - pre2.next = h2 - # 后段链表翻转完成了, 接下来进行间隔插入, 这个操作很简单 - pre = pre.next - pre2 = pre2.next - # 想要减少while内部判断, 就用节点数量少的链表作为判断依据 - while pre2.next != None: - pre3 = pre.next # pre3是pre的next - pre4 = pre2.next # pre4是pre2的next - pre.next = pre2 - pre2.next = pre3 - pre = pre3 - pre2 = pre4 - pre3 = pre.next - pre.next = pre2 - if pre3 != None: - pre2.next = pre3 - return head diff --git "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/206\347\277\273\350\275\254\346\225\264\344\270\252\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/206\347\277\273\350\275\254\346\225\264\344\270\252\351\223\276\350\241\250" deleted file mode 100644 index aef0110..0000000 --- "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/206\347\277\273\350\275\254\346\225\264\344\270\252\351\223\276\350\241\250" +++ /dev/null @@ -1,49 +0,0 @@ -# 反转一个单链表。 -# 示例: -# 输入: 1->2->3->4->5->NULL -# 输出: 5->4->3->2->1->NULL -# 进阶: -# 你可以迭代或递归地反转链表。你能否用两种方法解决这道题? - - -# 思路:翻转整个链表比起内部翻转链表更简单, 因为内部翻转链表是要在这个基础上添加一些判断的 -# 既然题目要求用迭代和递归来解答, 那我就附上两种解答 -# 先说迭代, 使用习惯使用的三指针h1(翻转后的next指向)h2(当前将要改变指向的节点) -# h3(由于h2改变指向后将没有办法找到h3节点, 所以事先记下h3) - - -# 迭代:98.48 -class Solution: - def reverseList(self, head): - if head == None: - return - h1 = None - h2 = head - h3 = h2.next - # while的判断可以用h1, h2, h3来判断, 但是由于三个指针有前后, 所以 - # 如果用靠后的h1来判断的话, 靠前的h3容易出现没有val的情况, 需要增加判断 - # 所以我采用最靠前的h3来判断, 以减少操作数 - while h3 != None: - h2.next = h1 - h1 = h2 - h2 = h3 - h3 = h3.next - # 由于使用h3来判断, 其实最后一个节点还没有连接好 - h2.next = h1 - return h2 - - -# 递归 和迭代一模一样的思路 94.42 -class Solution: - def reverseList(self, head): - if head == None: - return - return self.helper(None, head, head.next) - - - def helper(self, h1, h2, h3): - if h3 == None: - h2.next = h1 - return h2 - h2.next = h1 - return self.helper(h2, h3, h3.next) diff --git "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/234\345\233\236\346\226\207\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/234\345\233\236\346\226\207\351\223\276\350\241\250" deleted file mode 100644 index f4d4baa..0000000 --- "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/234\345\233\236\346\226\207\351\223\276\350\241\250" +++ /dev/null @@ -1,55 +0,0 @@ -# 请判断一个链表是否为回文链表。 -# 示例 1: -# 输入: 1->2 -# 输出: false -# 示例 2: -# 输入: 1->2->2->1 -# 输出: true -# 进阶: -# 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题? -# def isPalindrome(self, head: ListNode) -> bool: - - -# 思路:如果采用列表来解答的话是很简单的,但是不能作弊的话就要从列表和链表的区别来分析这道题 -# 他们的区别主要在于链表不能进行随机方法, 这正是我们想用列表的原因 -# 但是由于他要判断的是是否左右对称, 所以我们可以不需要进行暴力破解遍历n次链表, -# 只需要先到底链表的中间节点, 然后翻转左右链表中的一条, 就可以进行同步对比了, 难度不高, 但是麻烦 -# 核心技巧就是找到链表的中间节点和翻转链表, 我习惯使用迭代来解 - - -class Solution: - def isPalindrome(self, head): - if head == None: - return None - slow = fast = ListNode(None) - slow.next = head - # 寻找中间节点, 以下的写法会找到中间或中间偏左的节点 - while fast != None: - fast = fast.next - if fast == None: - break - fast = fast.next - slow = slow.next - h2 = slow.next - # 对于h2是否为空的判断很重要 - if h2 == None: - return True - slow.next = None - # 翻转链表的首要操作, 设定h1, 由于要分成两个链表, h1先为空 - h1 = None - h3 = h2.next - # 经典的选择最快的节点来进行判断, 可以减少while内部判断次数 - while h3 != None: - h2.next = h1 - h1 = h2 - h2 = h3 - h3 = h2.next - # 由于选择最快的节点作为判断, 最后一个非空节点还没有接好next, 补充接好 - h2.next = h1 - # 此时h2为翻转部分(右侧)翻转后的头节点 - while h2 != None: - if h2.val != head.val: - return False - h2 = h2.next - head = head.next - return True diff --git "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/24\351\200\242\344\272\214\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/24\351\200\242\344\272\214\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250" deleted file mode 100644 index a98857a..0000000 --- "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/24\351\200\242\344\272\214\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250" +++ /dev/null @@ -1,59 +0,0 @@ -# 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 -# 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 -# 示例: -# 给定 1->2->3->4, 你应该返回 2->1->4->3. -# def swapPairs(self, head: ListNode) -> ListNode: - - -# 思路:链表的内部翻转基本上是链表最难的操作了,解答的核心是注意对于要翻转的一段节点 -# 的前一个节点,后一个节点,以及这段要翻转的节点的内部的头尾都要做上标记,否则没法连上,用循环 -# 第一种解法是到了下一段开始才对上一段进行整理,第二种解法是到了当前段的最后,就进行整理 -# 思路基本一致,只是写法略有不同,个人感觉第二种解法写起来更加好写一些 - -class Solution: - def swapPairs(self, head): - pre = dummyhead = ListNode(None) - pre.next = head - k = 0 - # 过程中主要有3个指针:pre(上一个翻转后最后的位置)cur(这一次翻转前最后的位置)head(下一轮开始的位置) - while head != None: - if k == 2: - cur = head - k = 1 - elif k == 1: - cur.next = pre.next - pre.next = cur - pre = cur.next - pre.next = head - k = 2 - else: - k = 2 - head = head.next - if k == 1: - cur.next = pre.next - pre.next = cur - pre = cur.next - pre.next = head - return dummyhead.next - - -class Solution: - def swapPairs(self, head): - pre = dummyhead = ListNode(None) - dummyhead.next = head - cur = head - num = 1 - # num作为奇偶标记,cur是当前节点,font是新一段的首节点,pre是上一段的末节点 - while cur != None: - if num == 2: - font = cur.next - cur.next = pre.next - pre.next = cur - cur.next.next = font - pre = cur.next - cur = font - num = 1 - else: - cur = cur.next - num = 2 - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/25K\344\270\252\344\270\200\347\273\204\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/25K\344\270\252\344\270\200\347\273\204\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250" deleted file mode 100644 index e781ae6..0000000 --- "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/25K\344\270\252\344\270\200\347\273\204\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250" +++ /dev/null @@ -1,52 +0,0 @@ -# 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。 -# k 是一个正整数,它的值小于或等于链表的长度。 -# 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 -# 示例 : -# 给定这个链表:1->2->3->4->5 -# 当 k = 2 时,应当返回: 2->1->4->3->5 -# 当 k = 3 时,应当返回: 3->2->1->4->5 -# 说明 : -# 你的算法只能使用常数的额外空间。 -# 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 -# def reverseKGroup(self, head: ListNode, k: int) -> ListNode: - - -# 思路:这道题基本上是我见过的链表中最困难的题目之一,他的核心问题是内部翻转链表(更重要一点是内部链表有多个节点) -# 不过思路基本跟普通的内部翻转链表是一样的,不过对于要翻转多个节点这种情况来说,我们要按顺序的 -# 一个一个地进行翻转,我将采用循环的方式来写, 击败96%, 感动 - - -class Solution: - def reverseKGroup(self, head, k): - if head == None: - return None - if k == 1: - return head - pre = dummyhead = ListNode(None) - pre.next = head - num = 1 - # 从24题可以看出,这里有两种写法,1是当num重新为1时进行翻转,2是当num==k时进行翻转 - # 这里选用第二种,解答过程的核心在于前面提到的记录的变量, - # 我设pre为上一段已经翻转过之后最后的节点,head将到底下一段最开始的节点, - # pre2标记为这段节点的首节点(因为他将充当这段节点翻转之后的最后一个节点, 也就是下一个pre) - # 我们将从这一段的第一个节点开始进行翻转, 命名为h2,h1为这个节点翻转过后的next的节点 - # 所以最开始的h1是下一段的首节点, h3为翻转之前当前(h2)节点的下一个节点, 这是备份用的 - # 因为如果不事先备份的话等h2的next指向改变之后就找不到原来的next指向的那个节点了 - while head != None: - if num == k: - h1 = head = head.next - h2 = pre2 = pre.next - h3 = h2.next - h2.next = h1 - while h3 != head: - h1 = h2 - h2 = h3 - h3 = h2.next - h2.next = h1 - pre.next = h2 - pre = pre2 - num = 1 - else: - num += 1 - head = head.next - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/92\347\277\273\350\275\254\344\273\216m\345\210\260n\347\232\204\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/92\347\277\273\350\275\254\344\273\216m\345\210\260n\347\232\204\351\223\276\350\241\250" deleted file mode 100644 index 6aaafaa..0000000 --- "a/\351\223\276\350\241\250/\345\233\260\351\232\276:\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/92\347\277\273\350\275\254\344\273\216m\345\210\260n\347\232\204\351\223\276\350\241\250" +++ /dev/null @@ -1,41 +0,0 @@ -# 反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。 -# 说明: -# 1 ≤ m ≤ n ≤ 链表长度。 -# 示例: -# 输入: 1->2->3->4->5->NULL, m = 2, n = 4 -# 输出: 1->4->3->2->5->NULL -# def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: - - -# 思路:链表的内部翻转有固定套路,只要按照套路进行就可以了 - - -class Solution: - def reverseBetween(self, head, m, n): - if head == None or m == n: - return head - rec = 1 - cur = pre = dummyhead = ListNode(None) - dummyhead.next = head - # pre表示要翻转的一段的前一个节点, cur表示要翻转的一段的最后一个节点 - while head != None and rec <= n: - if rec == m - 1: - pre = head - elif rec == n: - cur = head - head = head.next - rec += 1 - h2 = pre.next - h1 = head - h3 = h2.next - # h1就是被翻转过后的内部节点, 当要翻转的一段的最后一个节点也翻转过了,内部翻转就完成了 - # 翻转前的首位节点直接接上当前head的节点(内部末尾与外部后半段连接已完成) - while h1 != cur: - h2.next = h1 - h1 = h2 - h2 = h3 - if h2 != None: - h3 = h2.next - # 内部翻转结束后, 把事先准备好的前一个节点接上新的内部首位节点 - pre.next = h1 - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\345\233\260\351\232\276\357\274\232\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/24\351\200\242\344\272\214\345\206\205\351\203\250\347\277\273\350\275\254" "b/\351\223\276\350\241\250/\345\233\260\351\232\276\357\274\232\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/24\351\200\242\344\272\214\345\206\205\351\203\250\347\277\273\350\275\254" deleted file mode 100644 index a98857a..0000000 --- "a/\351\223\276\350\241\250/\345\233\260\351\232\276\357\274\232\345\206\205\351\203\250\347\277\273\350\275\254\351\223\276\350\241\250/24\351\200\242\344\272\214\345\206\205\351\203\250\347\277\273\350\275\254" +++ /dev/null @@ -1,59 +0,0 @@ -# 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 -# 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 -# 示例: -# 给定 1->2->3->4, 你应该返回 2->1->4->3. -# def swapPairs(self, head: ListNode) -> ListNode: - - -# 思路:链表的内部翻转基本上是链表最难的操作了,解答的核心是注意对于要翻转的一段节点 -# 的前一个节点,后一个节点,以及这段要翻转的节点的内部的头尾都要做上标记,否则没法连上,用循环 -# 第一种解法是到了下一段开始才对上一段进行整理,第二种解法是到了当前段的最后,就进行整理 -# 思路基本一致,只是写法略有不同,个人感觉第二种解法写起来更加好写一些 - -class Solution: - def swapPairs(self, head): - pre = dummyhead = ListNode(None) - pre.next = head - k = 0 - # 过程中主要有3个指针:pre(上一个翻转后最后的位置)cur(这一次翻转前最后的位置)head(下一轮开始的位置) - while head != None: - if k == 2: - cur = head - k = 1 - elif k == 1: - cur.next = pre.next - pre.next = cur - pre = cur.next - pre.next = head - k = 2 - else: - k = 2 - head = head.next - if k == 1: - cur.next = pre.next - pre.next = cur - pre = cur.next - pre.next = head - return dummyhead.next - - -class Solution: - def swapPairs(self, head): - pre = dummyhead = ListNode(None) - dummyhead.next = head - cur = head - num = 1 - # num作为奇偶标记,cur是当前节点,font是新一段的首节点,pre是上一段的末节点 - while cur != None: - if num == 2: - font = cur.next - cur.next = pre.next - pre.next = cur - cur.next.next = font - pre = cur.next - cur = font - num = 1 - else: - cur = cur.next - num = 2 - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/141\347\216\257\345\275\242\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/141\347\216\257\345\275\242\351\223\276\350\241\250" deleted file mode 100644 index 047b503..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/141\347\216\257\345\275\242\351\223\276\350\241\250" +++ /dev/null @@ -1,51 +0,0 @@ -# 给定一个链表,判断链表中是否有环。 -# 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 -# 示例 1: -# 输入:head = [3,2,0,-4], pos = 1 -# 输出:true -# 解释:链表中有一个环,其尾部连接到第二个节点。 -# 示例 2: -# 输入:head = [1,2], pos = 0 -# 输出:true -# 解释:链表中有一个环,其尾部连接到第一个节点。 -# 示例 3: -# 输入:head = [1], pos = -1 -# 输出:false -# 解释:链表中没有环。 -# def hasCycle(self, head): -# head: ListNode -# return: bool - - -# 思路:快慢指针, 如果快指针能遇上慢指针的话,说明有环 -# 还有改变值的方法(取巧)把经过的节点的值改为特殊值,那么下次遇到就知道曾经遇到过了 - - -class Solution(object): - def hasCycle(self, head): - if head == None: - return False - if head.next == head: - return True - slow = fast = ListNode(None) - pre.next = head - while fast != None: - fast = fast.next - if fast == slow: - return True - if fast == None: - return True - fast = fast.next - slow = slow.next - return False - -class Solution(object): - def hasCycle(self, head): - if head == None: - return False - while head != None: - if head.val == None: - return True - head.val = None - head = head.next - return False diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/19\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/19\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271" deleted file mode 100644 index 95afc78..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/19\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271" +++ /dev/null @@ -1,29 +0,0 @@ -# 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 -# 示例: -# 给定一个链表: 1->2->3->4->5, 和 n = 2. -# 当删除了倒数第二个节点后,链表变为 1->2->3->5. -# 说明: -# 给定的 n 保证是有效的。 -# 进阶: -# 你能尝试使用一趟扫描实现吗? -# def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: - - -# 思路:采用快慢指针,让快指针比满指针先走N+1步,慢指针直接跳过下一个节点就可以 -# 难度不高,但是使用了一个链表修改技巧:快慢指针, 建议使用虚拟头节点 - - -class Solution: - def removeNthFromEnd(self, head, n): - if head == None: - return - dummyhead = ListNode(None) - dummyhead.next = head - slow = fast = dummyhead - for i in range(n+1): - fast = fast.next - while fast != None: - fast = fast.next - slow = slow.next - slow.next = slow.next.next - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/203\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\345\200\274\344\270\272\347\273\231\345\256\232\345\200\274\347\232\204\350\212\202\347\202\271" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/203\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\345\200\274\344\270\272\347\273\231\345\256\232\345\200\274\347\232\204\350\212\202\347\202\271" deleted file mode 100644 index 6550df2..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/203\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\345\200\274\344\270\272\347\273\231\345\256\232\345\200\274\347\232\204\350\212\202\347\202\271" +++ /dev/null @@ -1,22 +0,0 @@ -# 删除链表中等于给定值 val 的所有节点。 -# 示例: -# 输入: 1->2->6->3->4->5->6, val = 6 -# 输出: 1->2->3->4->5 -# def removeElements(self, head: ListNode, val: int) -> ListNode: - - -# 思路:指针pre从虚拟头节点开始, 用pre.next来检测是否为题目给定的值, 简单方便, -# 同时使用虚拟头节点可以避免很多麻烦的情况 - - -class Solution: - def removeElements(self, head, val): - pre = dummyhead = ListNode(None) - pre.next = head - while pre.next != None: - if pre.next.val == val: - # 注意如果next指针的值是val的话, pre不能向前移动噢 - pre.next = pre.next.next - else: - pre = pre.next - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/61\346\227\213\350\275\254\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/61\346\227\213\350\275\254\351\223\276\350\241\250" deleted file mode 100644 index a22a645..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/61\346\227\213\350\275\254\351\223\276\350\241\250" +++ /dev/null @@ -1,56 +0,0 @@ -# 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。 -# 示例 1: -# 输入: 1->2->3->4->5->NULL, k = 2 -# 输出: 4->5->1->2->3->NULL -# 解释: -# 向右旋转 1 步: 5->1->2->3->4->NULL -# 向右旋转 2 步: 4->5->1->2->3->NULL -# 示例 2: -# 输入: 0->1->2->NULL, k = 4 -# 输出: 2->0->1->NULL -# 解释: -# 向右旋转 1 步: 2->0->1->NULL -# 向右旋转 2 步: 1->2->0->NULL -# 向右旋转 3 步: 0->1->2->NULL -# 向右旋转 4 步: 2->0->1->NULL -# def rotateRight(self, head: ListNode, k: int) -> ListNode: - - -# 思路:采用快慢指针和虚拟头节点,可以先分成两段,重新连上 -# 注意:由于这里的k并没有说明是否会超出链表的上限,所以我决定先进行假设性记数 -# 如果发现超出上限的话这次记数将会提供给我们这段链表的长度 -# 击败99.7 开心 - - -class Solution: - def rotateRight(self, head, k): - if head == None: - return - if k == 0: - return head - pre = fast = dummyhead = ListNode(None) - fast.next = head - num = 0 - for i in range(k+1): - fast = fast.next - if fast == None: - break - num += 1 - # 如果是break出来的话num会小于k+1, 说明k超出了链表的上限, num就是链表有的节点数 - if num < k+1: # 这种情况k超过了链表上限 - k = k % num - fast = dummyhead - for i in range(k + 1): - fast = fast.next - while fast != None: - fast = fast.next - pre = pre.next - cur = pre.next - if cur == None: - return head - pre.next = None - dummyhead.next = cur - while cur.next != None: - cur = cur.next - cur.next = head - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/817\351\223\276\350\241\250\347\273\204\344\273\266" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/817\351\223\276\350\241\250\347\273\204\344\273\266" deleted file mode 100644 index b6778ca..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/817\351\223\276\350\241\250\347\273\204\344\273\266" +++ /dev/null @@ -1,52 +0,0 @@ -# 给定一个链表(链表结点包含一个整型值)的头结点 head。 -# 同时给定列表 G,该列表是上述链表中整型值的一个子集。 -# 返回列表 G 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 G 中)构成的集合。 -# 示例 1: -# 输入: -# head: 0->1->2->3 -# G = [0, 1, 3] -# 输出: 2 -# 解释: -# 链表中,0 和 1 是相连接的,且 G 中不包含 2,所以 [0, 1] 是 G 的一个组件,同理 [3] 也是一个组件,故返回 2。 -# 示例 2: -# 输入: -# head: 0->1->2->3->4 -# G = [0, 3, 1, 4] -# 输出: 2 -# 解释: -# 链表中,0 和 1 是相连接的,3 和 4 是相连接的,所以 [0, 1] 和 [3, 4] 是两个组件,故返回 2。 -# 注意: -# 如果 N 是给定链表 head 的长度,1 <= N <= 10000。 -# 链表中每个结点的值所在范围为 [0, N - 1]。 -# 1 <= G.length <= 10000 -# G 是链表中所有结点的值的一个子集. -# def numComponents(self, head: ListNode, G: List[int]) -> int: - - -# 思路:首先审题, 其实题意很简单, 用没有出现在列表中的整型值来把链表分成多段, -# 返回链表被分成的数量, 主要用到了双指针 - - -class Solution: - def numComponents(self, head, G): - if head == None: - return 0 - # 由于判断一个整型是否在列表中如果用循环的话会很麻烦, - # 所以做了一个哈希表, 或者用字典也可以 - visited = [False] * 10001 - for i in G: - visited[i] = True - pre = ListNode(-1) - # 双指针, 一前一后 - pre.next = head - res = 0 - while head != None: - # 如果当前指针的整型是列表中没有的, - # 前一个指针的整型是列表中有的, 那说明这又多了一个组件 - if not visited[head.val] and visited[pre.val]: - res += 1 - head = head.next - pre = pre.next - if visited[pre.val]: - res += 1 - return res diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/82\345\210\240\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271\344\270\215\344\277\235\347\225\231" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/82\345\210\240\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271\344\270\215\344\277\235\347\225\231" deleted file mode 100644 index 8b01ece..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/82\345\210\240\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271\344\270\215\344\277\235\347\225\231" +++ /dev/null @@ -1,41 +0,0 @@ -# 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。 -# 示例 1: -# 输入: 1->2->3->3->4->4->5 -# 输出: 1->2->5 -# 示例 2: -# 输入: 1->1->1->2->3 -# 输出: 2->3 -# def deleteDuplicates(self, head: ListNode) -> ListNode: - - -# 思路:用快慢指针+一个记录值, 难度不高, 用循环解(需要双while, 而且这里需要的指针比较麻烦) -# 更简单的思路是改写节点, 用递归解 -# 击败99.8 很开心 - - -class Solution: - def deleteDuplicates(self, head): - if head == None: - return - pre = dummyhead = ListNode(None) - pre.next = self.helper(head) - return pre.next - - - # 辅助函数的作用是判断自己 - # 传入一个节点, 如果节点发现自己有问题一直跳转到跟自己值不同的节点去,然后返回那个节点 - # 当然返回之前也要那个节点自己判断自己是否有问题 - # 如果节点自己没问题, 那就让节点的next节点自己判断有没有问题,把next节点指向判断过后的next节点 - def helper(self, node): - if node == None or node.next == None: - return node - if node.next.val == node.val: - total = node.val - while node != None and node.val == total: - node = node.next - if node != None: - node = self.helper(node) - return node - node.next = self.helper(node.next) - return node - diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/83\345\210\240\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271\344\270\224\344\277\235\347\225\231\344\270\200\344\270\252" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/83\345\210\240\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271\344\270\224\344\277\235\347\225\231\344\270\200\344\270\252" deleted file mode 100644 index c76c2ed..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/83\345\210\240\351\231\244\351\207\215\345\244\215\350\212\202\347\202\271\344\270\224\344\277\235\347\225\231\344\270\200\344\270\252" +++ /dev/null @@ -1,29 +0,0 @@ -# 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。 -# 示例 1: -# 输入: 1->1->2 -# 输出: 1->2 -# 示例 2: -# 输入: 1->1->2->3->3 -# 输出: 1->2->3 -# def deleteDuplicates(self, head: ListNode) -> ListNode: - - -# 思路:从迭代的角度来看这个问题比82题简单得多(因为不用删除掉重复元素第一次出现的节点), 用快慢指针直接解决 - - -class Solution: - def deleteDuplicates(self, head): - # head为慢指针, cur为快指针, 没有使用虚拟头节点 - if head == None: - return - cur = h1 = head - total = head.val - cur = cur.next - while cur != None: - if cur.val != total: - head.next = cur - head = head.next - total = cur.val - cur = cur.next - head.next = None - return h1 diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/86\345\210\206\351\232\224\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/86\345\210\206\351\232\224\351\223\276\350\241\250" deleted file mode 100644 index 0f102a5..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/86\345\210\206\351\232\224\351\223\276\350\241\250" +++ /dev/null @@ -1,31 +0,0 @@ -# 给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。 -# 你应当保留两个分区中每个节点的初始相对位置。 -# 示例: -# 输入: head = 1->4->3->2->5->2, x = 3 -# 输出: 1->2->2->4->3->5 -# def partition(self, head: ListNode, x: int) -> ListNode: - - -# 思路:用快慢指针迭代到最后就可以了, -# 注意最后要把后一段链表的末尾设为None, 因为末尾可能是原链表上的中间节点而不是None - - -class Solution: - def partition(self, head, x): - if head == None: - return - cur1 = pre1 = ListNode(None) - cur2 = pre2 = ListNode(None) - while head != None: - if head.val >= x: - cur2.next = head - cur2 = head - else: - cur1.next = head - cur1 = head - head = head.next - if cur2 == pre2: - return pre1.next - cur1.next = pre2.next - cur2.next = None - return pre1.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/147\351\223\276\350\241\250\344\275\277\347\224\250\346\217\222\345\205\245\346\216\222\345\272\217" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/147\351\223\276\350\241\250\344\275\277\347\224\250\346\217\222\345\205\245\346\216\222\345\272\217" deleted file mode 100644 index 5d148fe..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/147\351\223\276\350\241\250\344\275\277\347\224\250\346\217\222\345\205\245\346\216\222\345\272\217" +++ /dev/null @@ -1,42 +0,0 @@ -# 对链表进行插入排序。 -# 插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。 -# 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。 -# 插入排序算法: -# 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。 -# 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。 -# 重复直到所有输入数据插入完为止。 -# 示例 1: -# 输入: 4->2->1->3 -# 输出: 1->2->3->4 -# 示例 2: -# 输入: -1->5->3->4->0 -# 输出: -1->0->3->4->5 -# def insertionSortList(self, head: ListNode) -> ListNode: - - -# 思路:由于这个链表不是双向的, 所以普通列表中的插入排序是从接近新元素往开端走的, -# 但是链表这里只能是从开端往接近新元素的一边走了, 但是考虑到有可能遇到有序链表排序的情况 -# 留一个指针cur作为最接近新节点的指针, 先检查已排序部分最后一个指针是否小于等于新元素 - - -class Solution: - def insertionSortList(self, head): - if head == None: - return - dummy = ListNode(None) - dummy.next = head - cur = head - head = head.next - while head != None: - if head.val >= cur.val: - cur = head - head = head.next - else: - cur.next = head.next - pre = dummy - while pre.next.val < head.val: - pre = pre.next - head.next = pre.next - pre.next = head - head = cur.next - return dummy.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/160\347\233\270\344\272\244\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/160\347\233\270\344\272\244\351\223\276\350\241\250" deleted file mode 100644 index 5baa31a..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/160\347\233\270\344\272\244\351\223\276\350\241\250" +++ /dev/null @@ -1,36 +0,0 @@ -# 编写一个程序,找到两个单链表相交的起始节点。 -# 如下面的两个链表: -# 在节点 c1 开始相交。 -# 示例 1: -# 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 -# 输出:Reference of the node with value = 8 -# 输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。 -# def getIntersectionNode(self, headA, headB): -# headA, headB: ListNode -# return: ListNode - - -# 思路:题号往前翻一点遇到过与这题很相似的环形链表问题, 所以很直观的就可以想到使用字典 -# 或者直接对链表的值进行改写以达到标记'已遍历过'的标志,同时这道题要求给出具体的序号 -# 那么把节点值修改为先行开动的链表的序号的字符串形式, 以区别为遍历的整型形式会是一个不错的选择 -# 由于题目最后需要返回的是一个未经修改的节点, 所以改用字典来记录 -# 当然这道题还有一个很巧妙的双指针解法, 运用的是数学方法, 两个节点分别从两条链表的头部开始 -# 遍历, 当遍历完链表之后, 直接从另一条链表的头部继续开始遍历, 由于这样的遍历方式会使 -# 两个节点都遍历了2条链表的区别部分各一次和两条链表的公共部分一次, 所以两个节点将会 -# 在两条链表的公共部分的开端相遇, 此时提交这个节点就可以了(这个方法有一个很大的问题, -# 当一条链表是另一条链表的子链表时, 将不可能相遇(需要处理这个问题) -# 由于题目并没有太多的限制要求, 所以我选择写法和思路都很简单的字典的方法来解答 -# 果然数据结构就是强大, 简单粗暴击败99.95, 写起来还特别简洁, 要什么自行车? - - -class Solution(object): - def getIntersectionNode(self, headA, headB): - dct = {} - while headA != None: - dct[headA] = 0 - headA = headA.next - while headB != None: - if headB in dct: - return headB - headB = headB.next - return None diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/21\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/21\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250" deleted file mode 100644 index 1499e67..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/21\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250" +++ /dev/null @@ -1,29 +0,0 @@ -# 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  -# 示例: -# 输入:1->2->4, 1->3->4 -# 输出:1->1->2->3->4->4 -# def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: - - -# 思路:直接使用指针向前移动并判断大小即可 -# 一般来说如果涉及到链表的寻找中值并翻转等类似的操作时可能会使用递归,否则个人倾向于使用循环 -# 注意:leetcode上有跟这道题很类似的合并多个有序链表,思路基本一样,解起来稍微难一些 - - -class Solution: - def mergeTwoLists(self, l1, l2): - cur = pre = ListNode(None) - while l1 != None and l2 != None: - if l1.val <= l2.val: - res = l1.val - l1 = l1.next - else: - res = l2.val - l2 = l2.next - cur.next = ListNode(res) - cur = cur.next - if l1 != None: - cur.next = l1 - if l2 != None: - cur.next = l2 - return pre.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/2\344\270\244\346\225\260\347\233\270\345\212\240" "b/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/2\344\270\244\346\225\260\347\233\270\345\212\240" deleted file mode 100644 index f75417c..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225:\346\227\240\347\211\271\346\256\212\346\212\200\345\267\247/2\344\270\244\346\225\260\347\233\270\345\212\240" +++ /dev/null @@ -1,105 +0,0 @@ -# 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 -# 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 -# 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 -# 示例: -# 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) -# 输出:7 -> 0 -> 8 -# 原因:342 + 465 = 807 -# def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: - - -# 思路:由于这里题目给定的是逆序(我记得在leetcode上有对应的顺序的题目)逆序刚好可以保证是从个位数开始算 -# 所以既可以自制运算方法,也可以放进lst中最后计算,既然自制算法也并不是很麻烦,我这里选择自制运算方法(思路简单但是写起来麻烦) -# 然后用列表帮助记数,重建一个链表(思路和写法都很简单) -# 反思: -# 解法1 写起来超麻烦,下次可以考虑新建一个方法传入节点,在方法内部使用时把None当作0来用,应该会方便一些 -# 最终用时击败99%算是安慰吧, 附上写起来超轻松的,用列表的解法(主要是链表加了还要注意需不需要取余和新建节点实在太麻烦了) - - -class Solution: - def addTwoNumbers(self, l1, l2): - if l1 == None: - return l2 - elif l2 == None: - return l1 - ll = l1 - pre = ListNode(None) - pre.next = l1 - rec = 0 - while l1 != None and l2 != None: - res = rec + l1.val + l2.val - if res > 9: - l1.val = res % 10 - rec = 1 - else: - l1.val = res - rec = 0 - l1 = l1.next - l2 = l2.next - pre = pre.next - if rec == 0: - if l1 != None: - return ll - else: - pre.next = l2 - return ll - cur = pre - while rec != 0: - if l1 != None: - res = l1.val + rec - elif l2 != None: - res = l2.val + rec - else: - res = rec - if res > 9: - res = res % 10 - rec = 1 - else: - res = res - rec = 0 - if l1 != None: - l1.val = res - cur.next = l1 - l1 = l1.next - elif l2 != None: - cur.next = ListNode(res) - l2 = l2.next - else: - cur.next = ListNode(res) - cur = cur.next - if l1 != None: - cur.next = l1 - if l2 != None: - cur.next = l2 - return ll - - -class Solution: - def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: - if l1 == None: - return l2 - elif l2 == None: - return l1 - ll = l1 - lst1 = [] - lst2 = [] - while l1 != None and l2 != None: - lst1.insert(0, str(l1.val)) - lst2.insert(0, str(l2.val)) - l1 = l1.next - l2 = l2.next - while l1 != None: - lst1.insert(0, str(l1.val)) - l1 = l1.next - while l2 != None: - lst2.insert(0, str(l2.val)) - l2 = l2.next - res1 = ''.join(lst1) - res2 = ''.join(lst2) - res = str(int(res1) + int(res2)) - size = len(res) - cur = pre = ListNode(None) - for i in range(1, size+1): - cur.next = ListNode(int(res[-i])) - cur = cur.next - return pre.next diff --git "a/\351\223\276\350\241\250/\347\256\200\345\215\225\357\274\232\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/19\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271" "b/\351\223\276\350\241\250/\347\256\200\345\215\225\357\274\232\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/19\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271" deleted file mode 100644 index 95afc78..0000000 --- "a/\351\223\276\350\241\250/\347\256\200\345\215\225\357\274\232\345\277\253\346\205\242\346\214\207\351\222\210\344\270\216\350\231\232\346\213\237\345\244\264\350\212\202\347\202\271/19\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271" +++ /dev/null @@ -1,29 +0,0 @@ -# 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 -# 示例: -# 给定一个链表: 1->2->3->4->5, 和 n = 2. -# 当删除了倒数第二个节点后,链表变为 1->2->3->5. -# 说明: -# 给定的 n 保证是有效的。 -# 进阶: -# 你能尝试使用一趟扫描实现吗? -# def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: - - -# 思路:采用快慢指针,让快指针比满指针先走N+1步,慢指针直接跳过下一个节点就可以 -# 难度不高,但是使用了一个链表修改技巧:快慢指针, 建议使用虚拟头节点 - - -class Solution: - def removeNthFromEnd(self, head, n): - if head == None: - return - dummyhead = ListNode(None) - dummyhead.next = head - slow = fast = dummyhead - for i in range(n+1): - fast = fast.next - while fast != None: - fast = fast.next - slow = slow.next - slow.next = slow.next.next - return dummyhead.next diff --git "a/\351\223\276\350\241\250/\350\256\276\350\256\241\351\223\276\350\241\250" "b/\351\223\276\350\241\250/\350\256\276\350\256\241\351\223\276\350\241\250" deleted file mode 100644 index a222f1a..0000000 --- "a/\351\223\276\350\241\250/\350\256\276\350\256\241\351\223\276\350\241\250" +++ /dev/null @@ -1,122 +0,0 @@ -# 设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。 -# 在链表类中实现这些功能: -# get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。 -# addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。 -# addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 -# addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。 -# deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。 -# 示例: -# MyLinkedList linkedList = new MyLinkedList(); -# linkedList.addAtHead(1); -# linkedList.addAtTail(3); -# linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3 -# linkedList.get(1); //返回2 -# linkedList.deleteAtIndex(1); //现在链表是1-> 3 -# linkedList.get(1); //返回3 -# 提示: -# 所有val值都在 [1, 1000] 之内。 -# 操作次数将在  [1, 1000] 之内。 -# 请不要使用内置的 LinkedList 库。 - - -# 思路:感觉跟平时用的链表好像有些不同, 注意留一个尾节点, 再加一个size变量判断加入删除 -# 操作是否超出范围, 再加一个查看链表的函数 - - -class Node: - def __init__(self, val): - self.val = val - self.next = None - -class MyLinkedList: - - def __init__(self): - """ - Initialize your data structure here. - """ - self.pre = Node(None) - self.tail = self.pre - self.size = 0 - - def println(self): - lst = [] - cur = self.pre.next - while cur != None: - lst.append(str(cur.val)) - cur = cur.next - res = '->'.join(lst) - print(res) - - def get(self, index: int) -> int: - """ - Get the value of the index-th node in the linked list. If the index is invalid, return -1. - """ - if index + 1 > self.size or index < 0: - return -1 - cur = self.pre.next - num = 0 - while num < index: - cur = cur.next - num += 1 - return cur.val - - def addAtHead(self, val: int) -> None: - """ - Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. - """ - head = self.pre.next - self.pre.next = Node(val) - self.pre.next.next = head - if self.size == 0: - self.tail = self.pre.next - self.size += 1 - - def addAtTail(self, val: int) -> None: - """ - Append a node of value val to the last element of the linked list. - """ - self.tail.next = Node(val) - self.tail = self.tail.next - self.size += 1 - - def addAtIndex(self, index: int, val: int) -> None: - """ - Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. - """ - if index > self.size: - return -1 - cur = self.pre - num = 0 - while num < index: - cur = cur.next - num += 1 - head = cur.next - cur.next = Node(val) - cur.next.next = head - if index == self.size: - self.tail = self.tail.next - self.size += 1 - -def deleteAtIndex(self, index: int) -> None: - """ - Delete the index-th node in the linked list, if the index is valid. - """ - if index + 1 > self.size or index < 0: - return -1 - cur = self.pre - num = 0 - while num < index: - cur = cur.next - num += 1 - cur.next = cur.next.next - if index + 1 == self.size: - self.tail = cur - self.size -= 1 - -# Your MyLinkedList object will be instantiated and called as such: -# obj = MyLinkedList() -# param_1 = obj.get(index) -# obj.addAtHead(val) -# obj.addAtTail(val) -# obj.addAtIndex(index,val) -# obj.deleteAtIndex(index) diff --git "a/\351\223\276\350\241\250/\351\223\276\350\241\250\345\272\224\347\224\250\346\240\270\345\277\203\346\212\200\345\267\247\344\271\213\344\270\200\357\274\232876\345\257\273\346\211\276\344\270\255\351\227\264\350\212\202\347\202\271" "b/\351\223\276\350\241\250/\351\223\276\350\241\250\345\272\224\347\224\250\346\240\270\345\277\203\346\212\200\345\267\247\344\271\213\344\270\200\357\274\232876\345\257\273\346\211\276\344\270\255\351\227\264\350\212\202\347\202\271" deleted file mode 100644 index 9289e7b..0000000 --- "a/\351\223\276\350\241\250/\351\223\276\350\241\250\345\272\224\347\224\250\346\240\270\345\277\203\346\212\200\345\267\247\344\271\213\344\270\200\357\274\232876\345\257\273\346\211\276\344\270\255\351\227\264\350\212\202\347\202\271" +++ /dev/null @@ -1,32 +0,0 @@ -# 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。 -# 如果有两个中间结点,则返回第二个中间结点。 -# 示例 1: -# 输入:[1,2,3,4,5] -# 输出:此列表中的结点 3 (序列化形式:[3,4,5]) -# 返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。 -# 注意,我们返回了一个 ListNode 类型的对象 ans,这样: -# ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL. -# 示例 2: -# 输入:[1,2,3,4,5,6] -# 输出:此列表中的结点 4 (序列化形式:[4,5,6]) -# 由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。 -# 提示: -# 给定链表的结点数介于 1 和 100 之间。 -# def middleNode(self, head: ListNode) -> ListNode: - - -# 思路:链表使用的核心技巧之一:寻找中间节点, 我将用迭代的方式来写解 - - -class Solution: - def middleNode(self, head: ListNode) -> ListNode: - if head == None: - return None - cur = pre = head - while cur != None: - cur = cur.next - if cur == None: - break - cur = cur.next - pre = pre.next - return pre