1. 旋转链表(Medium) 给定一个链表,旋转链表,将链表每个节点向右移动 k  个位置,其中 k  是非负数。
示例 1: 
1 2 3 4 5 输入: 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: 
1 2 3 4 5 6 7 输入: 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 
 
解答: 
思路: 
链表中的点已经相连,一次旋转操作意味着:
先将链表闭合成环 
找到相应的位置断开这个环,确定新的链表头和链表尾 
 
新的链表头在哪里?
算法 
算法实现很直接:
找到旧的尾部并将其与链表头相连 old_tail.next = head,整个链表闭合成环,同时计算出链表的长度 n。 
找到新的尾部,第 (n - k % n - 1) 个节点 ,新的链表头是第 (n - k % n) 个节点。 
断开环 new_tail.next = None,并返回新的链表头 new_head。 
 
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 class  Solution (object  ):    def  rotateRight (self, head, k ):         """          :type head: ListNode         :type k: int         :rtype: ListNode         """         if  not  head:             return  None          if  not  head.next :             return  head         old_tail = head         n = 1          while  old_tail.next :             old_tail = old_tail.next              n += 1          old_tail.next  = head         new_tail = head         for  i in  range (n-k%n-1 ):             new_tail = new_tail.next          new_head = new_tail.next          new_tail.next  = None          return  new_head 
 
2. 不同路径(Medium) 一个机器人位于一个 m x n  网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
例如,上图是一个7 x 3 的网格。有多少可能的路径?
说明: m  和 n  的值均不超过 100。
示例 1: 
1 2 3 4 5 6 7 输入: m = 3, n = 2 输出: 3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 1. 向右 -> 向右 -> 向下 2. 向右 -> 向下 -> 向右 3. 向下 -> 向右 -> 向右 
 
示例 2: 
 
解答: 
思路一:动态规划 
很简单。
在考虑dp(m,n)时,可以从上方dp(m,n-1)来,也可以从左边dp(m-1,n)来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class  Solution (object  ):    def  uniquePaths (self, m, n ):         """          :type m: int         :type n: int         :rtype: int         """         if  m<1  or  n<1 :             return  0          dp = [[1 ] * m for  i 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 ] 
 
思路二:降低空间复杂度的动态规划 
好像所有的动态规划都可以做到空间复杂度降低。
优化:因为我们每次只需要 dp[i-1][j],dp[i][j-1]
所以我们只要记录这两个数,直接看代码吧!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class  Solution (object  ):    def  uniquePaths (self, m, n ):         """          :type m: int         :type n: int         :rtype: int         """         if  m<1  or  n<1 :             return  0          cur = [1 ]*n         for  i in  range (1 ,m):             for  j in  range (1 ,n):                 cur[j] += cur[j-1 ]         return  cur[-1 ] 
 
思路三:数学方法 
因为机器到底右下角,向下几步,向右几步都是固定的,
比如,m=3, n=2,我们只要向下 1 步,向右 2 步就一定能到达终点。
所以有$ C_{m+n-2}^{m-1}$
1 2 def  uniquePaths (self, m: int , n: int  ) -> int :        return  int (math.factorial(m+n-2 )/math.factorial(m-1 )/math.factorial(n-1 )) 
 
3. 不同路径2(Medium) 一个机器人位于一个 m x n  网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
说明: m  和 n  的值均不超过 100。
示例 1: 
1 2 3 4 5 6 7 8 9 10 11 12 输入: [   [0,0,0],   [0,1,0],   [0,0,0] ] 输出: 2 解释: 3x3 网格的正中间有一个障碍物。 从左上角到右下角一共有 2 条不同的路径: 1. 向右 -> 向右 -> 向下 -> 向下 2. 向下 -> 向下 -> 向右 -> 向右 
 
解答:
思路一:递归+DFS
很简单,很明显,但是超时。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class  Solution (object  ):    def  uniquePathsWithObstacles (self, obstacleGrid ):         """          :type obstacleGrid: List[List[int]]         :rtype: int         """         self.res = 0          m = len (obstacleGrid)         n = len (obstacleGrid[0 ])         def  travel (x,y ):             if  x == m-1  and  y == n-1  and  obstacleGrid[x][y] != 1 :                 self.res += 1              if  x +1  < m and  obstacleGrid[x+1 ][y] != 1 :                 travel(x+1 ,y)             if  y+1  < n and  obstacleGrid[x][y+1 ] != 1 :                 travel(x,y+1 )         if  obstacleGrid[0 ][0 ] == 1 :             return  0          travel(0 ,0 )         return  self.res 
 
思路二:动态规划 
算法 
如果第一个格点 obstacleGrid[0,0] 是 1,说明有障碍物,那么机器人不能做任何移动,我们返回结果 0。 
否则,如果 obstacleGrid[0,0] 是 0,我们初始化这个值为 1 然后继续算法。 
遍历第一行,如果有一个格点初始值为 1 ,说明当前节点有障碍物,没有路径可以通过,设值为 0 ;否则设这个值是前一个节点的值 obstacleGrid[i,j] = obstacleGrid[i,j-1]。 
遍历第一列,如果有一个格点初始值为 1 ,说明当前节点有障碍物,没有路径可以通过,设值为 0 ;否则设这个值是前一个节点的值 obstacleGrid[i,j] = obstacleGrid[i-1,j]。 
现在,从 obstacleGrid[1,1] 开始遍历整个数组,如果某个格点初始不包含任何障碍物,就把值赋为上方和左侧两个格点方案数之和 obstacleGrid[i,j] = obstacleGrid[i-1,j] + obstacleGrid[i,j-1]。 
如果这个点有障碍物,设值为 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 class  Solution (object  ):    def  uniquePathsWithObstacles (self, obstacleGrid ):         """          :type obstacleGrid: List[List[int]]         :rtype: int         """         if  not  obstacleGrid or  not  obstacleGrid[0 ]:             return  0          row = len (obstacleGrid)         col = len (obstacleGrid[0 ])         dp = [[0 ]*col for  _ in  range (row)]         dp[0 ][0 ] = 1  if  obstacleGrid[0 ][0 ] != 1  else  0          if  dp[0 ][0 ]==0 :             return  0          for  j in  range (1 ,col):             if  obstacleGrid[0 ][j] != 1 :                 dp[0 ][j] = dp[0 ][j-1 ]         for  i in  range (1 ,row):             if  obstacleGrid[i][0 ] != 1 :                 dp[i][0 ] = dp[i-1 ][0 ]         for  i in  range (1 ,row):             for  j in  range (1 ,col):                 if  obstacleGrid[i][j] != 1 :                     dp[i][j] = dp[i-1 ][j] + dp[i][j-1 ]         return  dp[-1 ][-1 ] 
 
4. 最小路径和(Medium) 给定一个包含非负整数的 m  x n  网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明: 每次只能向下或者向右移动一步。
示例: 
1 2 3 4 5 6 7 8 输入: [   [1,3,1],   [1,5,1],   [4,2,1] ] 输出: 7 解释: 因为路径 1→3→1→1→1 的总和最小。 
 
解答: 
思路:动态规划 
很简单的一道题
我们新建一个额外的 dp 数组,与原矩阵大小相同。在这个矩阵中,dp(i, j)表示从坐标 (i, j) 到右下角的最小路径权值。我们初始化右下角的 dp 值为对应的原矩阵值,然后去填整个矩阵,对于每个元素考虑移动到右边或者下面,因此获得最小路径和我们有如下递推公式:
$dp(i, j)= \mathrm{grid}(i,j)+\min\big(dp(i-1,j),dp(i,j-1)\big)$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class  Solution (object  ):    def  minPathSum (self, grid ):         """          :type grid: List[List[int]]         :rtype: int         """         if  not  grid:             return  0          row = len (grid)         col = len (grid[0 ])         dp = [[0 ] * col for  _ in  range (row)]         dp[0 ][0 ] = grid[0 ][0 ]         for  j in  range (1 ,col):             dp[0 ][j] = grid[0 ][j]+dp[0 ][j-1 ]         for  i in  range (1 ,row):             dp[i][0 ] = grid[i][0 ]+dp[i-1 ][0 ]         for  i in  range (1 ,row):             for  j in  range (1 ,col):                 dp[i][j] = grid[i][j] + min (dp[i-1 ][j],dp[i][j-1 ])         return  dp[-1 ][-1 ] 
 
当然,必存在可节约空间的做法。 
稍后奉上。 
5. 有效数字(Hard) 验证给定的字符串是否可以解释为十进制数字。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 "0"` => `true` `" 0.1 "` => `true` `"abc"` => `false` `"1 a"` => `false` `"2e10"` => `true` `" -90e3   "` => `true` `" 1e"` => `false` `"e3"` => `false` `" 6e-1"` => `true` `" 99e2.5 "` => `false` `"53.5e93"` => `true` `" --6 "` => `false` `"-+3"` => `false` `"95a54e53"` => `false 
 
说明:  我们有意将问题陈述地比较模糊。在实现代码之前,你应当事先思考所有可能的情况。这里给出一份可能存在于有效十进制数字中的字符列表:
数字 0-9 
指数 - “e” 
正/负号 - “+”/“-“ 
小数点 - “.” 
 
当然,在输入中,这些字符的上下文也很重要。
更新于 2015-02-10: C++函数的形式已经更新了。如果你仍然看见你的函数接收 const char * 类型的参数,请点击重载按钮重置你的代码。
解答: 
思路一:暴力枚举 
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 class  Solution :    def  isNumber (self, s: str  ):         s = s.strip()                  dot_seen = False          e_seen = False          num_seen = False          for  i, a in  enumerate (s):             if  a.isdigit():                 num_seen = True              elif  a == "." :                 if  e_seen or  dot_seen:                     return  False                  dot_seen = True              elif  a == "e" :                 if  e_seen or  not  num_seen:                     return  False                  num_seen = False                  e_seen = True              elif  a in  "+-" :                 if  i > 0  and  s[i - 1 ] != "e" :                     return  False              else :                 return  False          return  num_seen 
 
思路二:有限自动机DFA 
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 36 37 class  Solution :    def  isNumber (self, s: str  ) -> bool :         state = [             {},                          {"blank" : 1 , "sign" : 2 , "digit" : 3 , "." : 4 },                          {"digit" : 3 , "." : 4 },                          {"digit" : 3 , "." : 5 , "e" : 6 , "blank" : 9 },                          {"digit" : 5 },                          {"digit" : 5 , "e" : 6 , "blank" : 9 },                          {"sign" : 7 , "digit" : 8 },                          {"digit" : 8 },                          {"digit" : 8 , "blank" : 9 },                          {"blank" : 9 }         ]         cur_state = 1          for  c in  s:             if  c.isdigit():                 c = "digit"              elif  c in  " " :                 c = "blank"              elif  c in  "+-" :                 c = "sign"              if  c not  in  state[cur_state]:                 return  False              cur_state = state[cur_state][c]         if  cur_state not  in  [3 , 5 , 8 , 9 ]:             return  False          return  True  
 
tql