1. 简化路径(Medium) 以 Unix 风格给出一个文件的绝对路径 ,你需要简化它。或者换句话说,将其转换为规范路径。
在 Unix 风格的文件系统中,一个点(.
)表示当前目录本身;此外,两个点 (..
) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径
请注意,返回的规范路径必须始终以斜杠 /
开头,并且两个目录名之间必须只有一个斜杠 /
。最后一个目录名(如果存在)不能 以 /
结尾。此外,规范路径必须是表示绝对路径的最短 字符串。
示例 1:
1 2 3 输入:"/home/" 输出:"/home" 解释:注意,最后一个目录名后面没有斜杠。
示例 2:
1 2 3 输入:"/../" 输出:"/" 解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
示例 3:
1 2 3 输入:"/home//foo/" 输出:"/home/foo" 解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例 4:
1 2 输入:"/a/./b/../../c/" 输出:"/c"
示例 5:
1 2 输入:"/a/../../b/../c//.//" 输出:"/c"
示例 6:
1 2 输入:"/a//b////c/d//././/.." 输出:"/a/b/c"
解答:
思路:
非常简单的模拟题,利用一个栈来储存当前的路径。用 “/“ 将输入的全路径分割成多个部分,对于每一个部分循环处理:如果为空或者 “.” 则忽略,如果是 “..” ,则出栈顶部元素(如果栈为空则忽略),其他情况直接压入栈即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution (object ): def simplifyPath (self, path ): """ :type path: str :rtype: str """ stack = [] for item in path.split('/' ): if item and item != '.' : if item == '..' : if stack: stack.pop() else : stack.append(item) if not stack: return '/' else : return '/' +'/' .join(stack)
2. 编辑距离(Hard) 给定两个单词 word1 和 word2 ,计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
示例 1:
1 2 3 4 5 6 输入: word1 = "horse", word2 = "ros" 输出: 3 解释: horse -> rorse (将 'h' 替换为 'r') rorse -> rose (删除 'r') rose -> ros (删除 'e')
示例 2:
1 2 3 4 5 6 7 8 输入: word1 = "intention", word2 = "execution" 输出: 5 解释: intention -> inention (删除 't') inention -> enention (将 'i' 替换为 'e') enention -> exention (将 'n' 替换为 'x') exention -> exection (将 'n' 替换为 'c') exection -> execution (插入 'u')
解答:
思路:动态规划
其实这个题很简单。如果你学过编辑距离的话。
就是一个动态规划。
dp(i,j) = min(dp(i-1,j)+1,dp(i,j-1)+1,dp(i-1,j-1 + tmp))
Tmp = 0 if w[i] == s[j] else 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution (object ): def minDistance (self, word1, word2 ): """ :type word1: str :type word2: str :rtype: int """ n = len (word1) m = len (word2) if n == 0 or m == 0 : return max (n,m) dp = [[i+j for j in range (m+1 )] for i in range (n+1 )] for i in range (1 ,n+1 ): for j in range (1 ,m+1 ): tmp = 0 if word1[i-1 ] == word2[j-1 ] else 1 dp[i][j] = min (dp[i-1 ][j]+1 ,dp[i][j-1 ]+1 ,dp[i-1 ][j-1 ]+tmp) return dp[-1 ][-1 ]
3. 矩阵置零(Medium) 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地 算法。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 输入: [ [1,1,1], [1,0,1], [1,1,1] ] 输出: [ [1,0,1], [0,0,0], [1,0,1] ]
示例 2:
1 2 3 4 5 6 7 8 9 10 11 12 输入: [ [0,1,2,0], [3,4,5,2], [1,3,1,5] ] 输出: [ [0,0,0,0], [0,4,5,0], [0,3,1,0] ]
进阶:
一个直接的解决方案是使用 O(m**n ) 的额外空间,但这并不是一个好的解决方案。
一个简单的改进方案是使用 O(m + n ) 的额外空间,但这仍然不是最好的解决方案。
你能想出一个常数空间的解决方案吗?
解答:
思路一:
如果矩阵中任意一个格子有零我们就记录下它的行号和列号,这些行和列的所有格子在下一轮中全部赋为零。
算法
我们扫描一遍原始矩阵,找到所有为零的元素。
如果我们找到 [i, j] 的元素值为零,我们需要记录下行号 i 和列号 j。
用两个 sets ,一个记录行信息一个记录列信息。
最后,我们迭代原始矩阵,对于每个格子检查行 r 和列 c 是否被标记过,如果是就将矩阵格子的值设为 0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution (object ): def setZeroes (self, matrix ): """ :type matrix: List[List[int]] :rtype: None Do not return anything, modify matrix in-place instead. """ row = len (matrix) col = len (matrix[0 ]) rows,cols = set (),set () for i in range (row): for j in range (col): if matrix[i][j] == 0 : rows.add(i) cols.add(j) for i in range (row): for j in range (col): if i in rows or j in cols: matrix[i][j] = 0
思路二:常数空间
关键思想: 用matrix第一行和第一列记录该行该列是否有0,作为标志位
但是对于第一行,和第一列要设置一个标志位,为了防止自己这一行(一列)也有0的情况.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution : def setZeroes (self, matrix: List [List [int ]] ) -> None : """ Do not return anything, modify matrix in-place instead. """ row = len (matrix) col = len (matrix[0 ]) row0_flag = False col0_flag = False for j in range (col): if matrix[0 ][j] == 0 : row0_flag = True break for i in range (row): if matrix[i][0 ] == 0 : col0_flag = True break for i in range (1 , row): for j in range (1 , col): if matrix[i][j] == 0 : matrix[i][0 ] = matrix[0 ][j] = 0 for i in range (1 , row): for j in range (1 , col): if matrix[i][0 ] == 0 or matrix[0 ][j] == 0 : matrix[i][j] = 0 if row0_flag: for j in range (col): matrix[0 ][j] = 0 if col0_flag: for i in range (row): matrix[i][0 ] = 0
4. 搜索二维矩阵(Medium) 编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:
1 2 3 4 5 6 7 8 输入: matrix = [ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ] target = 3 输出: true
示例 2:
1 2 3 4 5 6 7 8 输入: matrix = [ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ] target = 13 输出: false
解答:
思路:很明显用二分法,不假思索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution (object ): def searchMatrix (self, matrix, target ): """ :type matrix: List[List[int]] :type target: int :rtype: bool """ if not matrix or not matrix[0 ]: return False row = len (matrix) col = len (matrix[0 ]) l,r = 0 ,row*col-1 while l <= r: mid = (l+r)>>1 value = matrix[mid//col][mid%col] if target == value: return True elif target < value: r = mid -1 else : l = mid + 1 return False
5. 颜色分类(Medium) 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意: 不能使用代码库中的排序函数来解决这道题。
示例:
1 2 输入: [2,0,2,1,1,0] 输出: [0,0,1,1,2,2]
进阶:
一个直观的解决方案是使用计数排序的两趟扫描算法。 首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?
解答:
思路:
以前见过这道题,第一时间想到双指针,但是没办法记录当前指针位置。
所以很明显,三指针法。
我们用三个指针(begin, end 和curr)来分别追踪0的最右边界,2的最左边界和当前考虑的元素。
这里是用三个指针,begin, cur, end,cur需要遍历整个数组
cur 指向0,交换begin与cur, begin++,cur++
cur 指向1,不做任何交换,cur++
cur 指向2,交换end与cur,end–
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution (object ): def sortColors (self, nums ): """ :type nums: List[int] :rtype: None Do not return anything, modify nums in-place instead. """ p0 = curr = 0 p2 = len (nums) - 1 while curr <= p2: if nums[curr] == 0 : nums[p0],nums[curr] = nums[curr],nums[p0] p0 += 1 curr += 1 elif nums[curr] == 2 : nums[p2],nums[curr] = nums[curr],nums[p2] p2 -= 1 else : curr += 1
几个易错点:
一定要按照这个顺序来比较,先比较0,再比较2,再比较1,具体可以灵活,需要自己领悟。
一定是if-elif-else的顺序
思路二:
考虑数字和index之间的关系,从而替换数字。
这个思路明显,很巧妙。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution (object ): def sortColors (self, nums ): """ :type nums: List[int] :rtype: void Do not return anything, modify nums in-place instead. """ n0, n1, n2 = -1 , -1 , -1 for i in range (len (nums)): if nums[i] == 0 : n0, n1, n2 = n0+1 , n1+1 , n2+1 nums[n2] = 2 nums[n1] = 1 nums[n0] = 0 elif nums[i] == 1 : n1, n2 = n1+1 , n2+1 nums[n2] = 2 nums[n1] = 1 else : n2 += 1 nums[n2] = 2