[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:
输入:n = 4, leftChild = \([1,-1,3,-1]\), rightChild = \([2,-1,-1,-1]\)
输出:true
示例 2:
输入:n = 4, leftChild = \([1,-1,3,-1]\), rightChild = \([2,3,-1,-1]\)
输出:false
示例 3:
输入:n = 2, leftChild = \([1,0]\), rightChild = \([-1,-1]\)
输出:false
示例 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