[Leetcode Weekly Contest]177

链接:LeetCode

[Leetcode]5169. 日期之间隔几天

编写一个程序来计算两个日期之间隔了多少天。

日期以字符串形式给出,格式为 YYYY-MM-DD,如示例所示。

示例 1:
输入:date1 = "2019-06-29", date2 = "2019-06-30"
输出:1

求两个日期之间的间隔,要考虑的几个问题有:注意是否是闰年;间隔要取绝对值。我们可以分别求两个日期与1971年1月1日的间隔,然后取差即可。另外,也可以直接调用python库求解。

from datetime import datetime
class Solution:
    # def daysBetweenDates(self, date1: str, date2: str) -> int:
    #     date1 = datetime.strptime(date1,'%Y-%m-%d')
    #     date2 = datetime.strptime(date2,'%Y-%m-%d')
    #     res = abs((date1 - date2).days)
    #     return res

    def daysBetweenDates(self, date1: str, date2: str) -> int:
        self.month = [[0,31,28,31,30,31,30,31,31,30,31,30,31],[0,31,29,31,30,31,30,31,31,30,31,30,31]]
        self.day = [365,366]
        year1,month1,day1 = [int(x) for x in date1.split('-')]
        year2,month2,day2 = [int(x) for x in date2.split('-')]
        s1,s2 = self.gap(year1,month1,day1),self.gap(year2,month2,day2)
        return abs(s1-s2)

    def gap(self,year,month,day):
        res = 0
        flag = self.isleapyear(year)
        for i in range(1971,year):
            res += self.day[self.isleapyear(i)]
        for i in range(month):
            res += self.month[self.isleapyear(year)][i]
        res += day
        return res

    def isleapyear(self,year):
        if (year%4 == 0 and year%100!=0) or year%400==0:
            return True
        return False

[Leetcode]5170. 验证二叉树

二叉树上有\(n\)个节点,按从 0 到 n - 1 编号,其中节点 i 的两个子节点分别是\(leftChild[i]\)\(rightChild[i]\)
只有 所有 节点能够形成且 只 形成 一颗 有效的二叉树时,返回 true;否则返回 false。
如果节点\(i\)没有左子节点,那么\(leftChild[i]\)就等于\(-1\)。右子节点也符合该规则。
注意:节点没有值,本问题中仅仅使用节点编号。
示例 1:
示例 1
输入:n = 4, leftChild = \([1,-1,3,-1]\), rightChild = \([2,-1,-1,-1]\)
输出:true
示例 2:
示例 2
输入:n = 4, leftChild = \([1,-1,3,-1]\), rightChild = \([2,3,-1,-1]\)
输出:false
示例 3:
示例 3
输入:n = 2, leftChild = \([1,0]\), rightChild = \([-1,-1]\)
输出:false
示例 4:
示例 4
输入:n = 6, leftChild = \([1,-1,-1,4,-1,-1]\), rightChild = \([2,-1,-1,5,-1,-1]\)
输出:false

这一题的示例比较重要,我们可以从示例中找到很多case。对于一个二叉树,它有以下特征:

  • 一个结点最多只有另外一个结点指向它(bad case:示例 2)
  • 两个结点不能相互指向(bad case:示例 3)
  • 必须是一个连通图(bad case:示例 4)

找出这三个case,那么其他不满足的都是非二叉树。第一个条件,我们只需要遍历以下数组即可,第二个条件,我们可以通过并查集在\(O(N)\)时间复杂度判断出来,最后一个条件也可以通过并查集解决。

class Solution:
    def validateBinaryTreeNodes(self, n: int, leftChild: List[int], rightChild: List[int]) -> bool:
        children = leftChild+rightChild
        count = collections.Counter(children)
        for i in range(n):
            if count[i] > 1:
                return False

        dic = {}
        def find(p):
            while p!=dic[p]:
                p = dic[p]
            return p
        def union(p,q):
            root1,root2 = find(p),find(q)
            if root1==root2:
                return False
            else:
                dic[root1] = root2
                return True
        for i in range(n):
            dic[i] = i
        for i in range(n):
            if leftChild[i]!=-1:
                if not union(leftChild[i],i):
                    return False
            if rightChild[i]!=-1:
                if not union(rightChild[i],i):
                    return False
        root = find(0)
        for i in range(n):
            if find(i) != root:
                return False
        return True

[Leetcode]5171.最接近的因数

给你一个整数 num,请你找出同时满足下面全部要求的两个整数:
两数乘积等于  num + 1 或 num + 2
以绝对差进行度量,两数大小最接近
你可以按任意顺序返回这两个整数。

示例 1:
输入:num = 8
输出:\([3,3]\)
解释:对于 num + 1 = 9,最接近的两个因数是 3 & 3;对于 num + 2 = 10, 最接近的两个因数是 2 & 5,因此返回 3 & 3 。

由于是查找最接近的两个因数,从平方根可以查起即可,当出现积为target,则必定是最近的两个数。并且可以将判断num+2 以及判断num+1放在一个for循环中,因为i是确定的,如果(num+1)%i==0 (num+1)/i-i肯定是小于(num+2)/i-i。

class Solution:
    def closestDivisors(self, num: int) -> List[int]:
        n1,n2 = num+1,num+2
        val = int((n2)**0.5)
        for i in reversed(range(val+1)):
            if n1%i == 0:
                return [i,n1//i]
            if n2%i == 0:
                return [i,n2//i]

[Leetcode]5172. 形成三的最大倍数

给你一个整数数组 digits,你可以通过按任意顺序连接其中某些数字来形成\(3\)的倍数,请你返回所能得到的最大的\(3\)的倍数。
由于答案可能不在整数数据类型范围内,请以字符串形式返回答案。
如果无法得到答案,请返回一个空字符串。

示例 1:
输入:digits = \([8,1,9]\)
输出:"981"
示例 2:
输入:digits = \([8,6,7,1,0]\)
输出:"8760"
示例 3:
输入:digits = \([1]\)
输出:""
示例 4:
输入:digits = \([0,0,0,0,0,0]\)
输出:"0"

这道题的关键是"3"的最大倍数,如果是一个普通的数,一般的朴素思想是dfs,但因为这里规定了是3,那么我们便可以找出3的倍数的一些特征。
首先,很明显的,对3的倍数的几个数字相加一定任然是3的倍数;并且,对于一个数而言,对3求余,只会出现0,1,2三张情况。那么我们可以得到以下结论:
如果取模3等于0,那其实可以都要,如果是1,那就得去掉一个1或者两个2,如果是2那就得去掉一个2或者两个1.而这些删掉一个数的函数其实是类似的,可以反复调用。注意在如果全是0输出0而不是00000. 而且要在删完数之后判断。并且,我们通过哈希表存储个数,最后输出的时候也不需要另外排序了,从大到小输出即可。

import collections
class Solution:
    def largestMultipleOfThree(self, digits: List[int]) -> str:
        count = collections.Counter(digits)
        sum_ = sum(digits)
        if sum_%3 == 1:
            if not self.delDigit(count,1):
                for i in range(2):
                    self.delDigit(count,2)
        if sum_%3 == 2:
            if not self.delDigit(count,2):
                for i in range(2):
                    self.delDigit(count,1)
        res = ''
        for i in reversed(range(10)):
            for _ in range(count[i]):
                res += str(i)
        if res and int(res) == 0:
            return '0'
        return res

    def delDigit(self,count,num):
        for i in range(num,10,3):
            if count[i]:
                count[i] -= 1
                return True
        return False
posted @ 2020-02-24 10:44  Jamest  阅读(167)  评论(0编辑  收藏  举报