[Leetcode Weekly Contest]181

链接:LeetCode

[Leetcode]1389. 按既定顺序创建目标数组

给你两个整数数组 nums 和 index。你需要按照以下规则创建目标数组:

  • 目标数组 target 最初为空。
  • 按从左到右的顺序依次读取 nums[i] 和 index[i],在 target 数组中的下标 index[i] 处插入值 nums[i] 。
  • 重复上一步,直到在 nums 和 index 中都没有要读取的元素。
    请你返回目标数组。
    题目保证数字插入位置总是存在。

直接insert即可,如下。

class Solution:
    def createTargetArray(self, nums: List[int], index: List[int]) -> List[int]:
        res = []
        for i in range(len(index)):
            res.insert(index[i],nums[i])
        return res

[Leetcode]1390. 四因数

给你一个整数数组 nums,请你返回该数组中恰有四个因数的这些整数的各因数之和。
如果数组中不存在满足题意的整数,则返回 0 。

示例:
输入:\(nums = [21,4,7]\)
输出:32
解释:
21 有 4 个因数:1, 3, 7, 21
4 有 3 个因数:1, 2, 4
7 有 2 个因数:1, 7
答案仅为 21 的所有因数的和。

除了暴力方法去求整数因数的个数,一个比较巧妙的想法是:四个因数就是能够分解成两个质数乘积的数或者是立方数。
比如:
21 = 3 * 7
8 = 2 * 4

class Solution:
    def sumFourDivisors(self, nums: List[int]) -> int:
        if not nums:
            return 0
        max_num = max(nums)
        isPrim = [True for _ in range(max_num)]
        for i in range(2,max_num):
            if not isPrim[i]:continue
            isPrim[i+i:max_num:i] = [False] * len(isPrim[i+i:max_num:i])

        # 把素数都提取出来
        prims = [i for i in range(2, max_num) if isPrim[i]]
        res = 0
        for num in nums:
            for prim in prims:
                if prim * prim > num:
                    break
                elif prim * prim * prim == num:
                    res += (1 + num + prim + prim * prim)
                elif num % prim == 0 and isPrim[num // prim] and prim * prim != num:
                    res += (1 + num + prim + num // prim)
        return res

[Leetcode]1391. 检查网格中是否存在有效路径

给你一个 m x n 的网格 grid。网格里的每个单元都代表一条街道。\(grid[i][j]\)的街道可以是:

  • 1 表示连接左单元格和右单元格的街道。
  • 2 表示连接上单元格和下单元格的街道。
  • 3 表示连接左单元格和下单元格的街道。
  • 4 表示连接右单元格和下单元格的街道。
  • 5 表示连接左单元格和上单元格的街道。
  • 6 表示连接右单元格和上单元格的街道。

你最开始从左上角的单元格 (0,0) 开始出发,网格中的「有效路径」是指从左上方的单元格 (0,0) 开始、一直到右下方的 (m-1,n-1) 结束的路径。该路径必须只沿着街道走。
如果网格中存在有效的路径,则返回 true,否则返回 false 。

一道图遍历的题目,难点在于单元的表示和判断是否存在环。这里通过BFS,新建一个队列,每次判断是否能进入下一个单元,以及进入的路径。如下。

import collections
class Solution:
    def hasValidPath(self, grid: List[List[int]]) -> bool:
        dir = {1:[(0,1),(0,-1)],
               2:[(1,0),(-1,0)],
               3:[(1,0),(0,-1)],
               4:[(0,1),(1,0)],
               5:[(0,-1),(-1,0)],
               6:[(0,1),(-1,0)]}

        queue = collections.deque()
        queue.append([0,0])
        m,n = len(grid),len(grid[0])
        if n==m==1:
            return True
        while queue:
            x,y = queue.popleft()
            for dx,dy in dir[grid[x][y]]:
                nx,ny = x+dx,y+dy
                if 0<=nx<m and 0<=ny<n and grid[nx][ny]!=-1:
                    for ndx,ndy in dir[grid[nx][ny]]:
                        if ndx+dx==0 and ndy+dy==0:
                            if nx==m-1 and ny==n-1:
                                return True
                            queue.append((nx,ny))
            grid[x][y]=-1
        return False

[Leetcode]1392. 最长快乐前缀

「快乐前缀」是在原字符串中既是 非空 前缀也是后缀(不包括原字符串自身)的字符串。
给你一个字符串 s,请你返回它的 最长快乐前缀。
如果不存在满足题意的前缀,则返回一个空字符串。

KMP 算法中的 next 数组描述的就是字符串中前缀与后缀的最长匹配长度,注意这里要加一个特殊字符,这样next最后一个值才表示整个字符串的最长前后缀。

class Solution:
    def longestPrefix(self, s: str) -> str:
        next = self.get_next(s+'*')
        return s[:next[-1]]

    def get_next(self,p):
        len_p = len(p)
        next = [-1 for i in range(len_p)]
        j,k = 0,-1
        while j<len_p-1:
            if p[j] == p[k] or k==-1:
                j+=1
                k+=1
                next[j] = k
            else:
                k = next[k]
        return next

参考:
四因数

posted @ 2020-03-24 07:56  Jamest  阅读(285)  评论(0编辑  收藏  举报