LeetCode刷题之路(五)——medium的进阶

Problem 39. Combination Sum

  给定一个没有重复数字的数组和一个target,返回所有数组中的数求和为target的组合,每个数字可以重复利用

  **解题思路:**backtracking,该方法可以用来解决一类问题。注意边界值的处理

 class Solution(object):  
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        res = []
        self.search(candidates, target, 0, [], res)
        return res

    def search(self, candidates, target, idx, t_res, res):
        if target == 0:
            res.append(sorted(t_res))
            return

        for i in range(idx, len(candidates)):
            if target < candidates[i]:
                continue
            t_res.append(candidates[i])
            self.search(candidates, target-candidates[i], i,  t_res , res)
            t_res.pop()

  注意idx的传递,因为可以重复使用,循环里面提前判断当前target是不是够减,可以减少需要的操作


Problem 40. Combination SumII

  同Problem 39,不同的地方就是每个数字只能用一次,采用相同的方法,传递的idx每次加1即可


Problem 43. Multiply Strings

  给定两个字符串,每个字符均为’0’-‘9’,求解两个字符串代表的数字的乘积并返回
  解题思路:列出乘法竖式,我们可以看到对应于L两个字符串下标分别为i,j的数字的乘积,在结果中的位置。长度为a和b的字符串相乘,结果res最长为a+b,其i和j相乘的结果,位于res索引的i+j和i+j+1的位置。

class Solution(object):
    def multiply(self, num1, num2):
        res = [0] * (len(num1) + len(num2))

        for i in range(len(num1)-1, -1, -1):
            for j in range(len(num2)-1, -1, -1):
                mul = int(num1[i]) * int(num2[j])
                carry = i + j
                mod = i + j + 1
                t = mul + res[mod]
                res[carry] += t // 10
                res[mod] = t % 10
        mul_res = 0
        for i in res:
            mul_res *= 10
            mul_res += i
        return str(mul_res)

Problem 46. Permutations

  给定一个list(没有重复值),求出它所有可能的排列组合
  解题思路:同Problem 39这类问题都可以用backtrack求解,特别注意,python里面如果用一个list,a.append(b)之后,对b的所有操作都会影响到之前a中添加的那个b,因此要使用a.append(list(b)),重新申请内存。

def search(nums, t, res):

    if len(t) == len(nums):
        res.append(list(t))#不能直接append(t),否则res里面的内容会随着后续对t的操作而发生改变
        return 
    for i in nums:
        if i in t:
            continue
        t.append(i)
        search(nums, t, res)
        t.pop()


class Solution(object):  
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        search(nums, [], res)
        return res

Problem 48. Rotate Image

  给定一个方形的图像,顺时针旋转90,要求in-place
  解题思路:先上下翻转,然后转置。如果要逆时针旋转的话,只需先左右翻转即可。

def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        matrix.reverse()#如果这里不能reverse,可以直接循环求解
        n = len(matrix)
        for i in range(n):
            for j in range(i+1, n):
                t = matrix[i][j]
                matrix[i][j] = matrix[j][i]
                matrix[j][i] = t

PS:python有个trick,discussion里面提到的,用切片可以一步解决(对于非方阵,依旧有效)

def rotate(self, matrix):

        matrix[::] = zip(*matrix[::-1])

Problem 49. Group Anagrams

  **给定一个包含str的list,返回一个list,这个list的每一个元素也是一个list,该list里面所有的单词由相同的字母组成:譬如给定[“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],返回:
[
[“ate”, “eat”,”tea”],
[“nat”,”tan”],
[“bat”]
]**。
  解题思路:遍历每个str,先排序,然后用一个字典维护具有相同字母的单词有哪些。

  def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        d = {}
        for i in strs:
            s_i = str(sorted(i))
            if s_i not in d:
                d[s_i] =[i]
            else:
                d[s_i].append(i)
        return d.values()

Problem 54. Spiral Matrix

  给定一个矩阵,顺时针旋转打印,由外到内,譬如给定[[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]],输出[1, 2, 3, 4, 7, 10, 9, 8, 7, 4, 5, 6]
  解题思路:给定两个点,左上角和右下角,然后按照左->右,上->下,右->左,下->上,然后左上角往右下移动,右上角往左上移动,循环以上四个打印步骤,直至定位点相遇,注意,因为可能不是方阵,所有打印的后两个步骤要进行判断是否只有一行或者一列,避免重复打印。

  解题思路2:1.打印第一行,即list[0],然后从list删除list[0];2.将list逆时针旋转90度,重复1,

   def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        return matrix and list(matrix.pop(0)) + self.spiralOrder(zip(*matrix)[::-1])

Problem 55. Jump Game

  给定一个非负数的列表,每个数代表在当前位置能向前跳的最大步数,问是否能到达列表尾部
  解题思路:核心就是要考虑0的情况,有如下几种:

     1. 列表长度为1,return True
     2. 在列表尾碰到0,return True
     3. 在中间碰到0,那么就要看0之前能迈出的最大步数是否大于2,即能否跨过这个0,如果不行就return False,如果可以就继续往前。
     4. 当前位置的max_step=max(max_step-1,nums[i]),初始化为nums[0]。
   def canJump(self, nums):
        if len(nums) == 1:
            return True
        max_step = nums[0]
        for i in range(len(nums)):        
            if nums[i] == 0 :
                if i == len(nums) - 1:
                    return True
                if max_step <2:
                    return False             
            max_step = max(max_step-1, nums[i])           
        return True           

你可能感兴趣的:(leetcode)