LeetCode 笔记十四 【算法】1013. 将数组分成和相等的三个部分 +【数据库】176. 第二高的薪水

昨天忘记刷题唉😔

【算法】1013. 将数组分成和相等的三个部分

题目:

给你一个整数数组 A,只有可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false。
形式上,如果可以找出索引 i+1 < j 且满足 (A[0] + A[1] + … + A[i] == A[i+1] + A[i+2] + … + A[j-1] == A[j] + A[j-1] + … + A[A.length - 1]) 就可以将数组三等分。

示例 1:

输出:[0,2,1,-6,6,-7,9,1,2,0,1]
输出:true
解释:0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1

示例 2:

输入:[0,2,1,-6,6,7,9,-1,2,0,1]
输出:false

示例 3:

输入:[3,3,6,5,-2,2,5,1,-9,4]
输出:true
解释:3 + 3 = 6 = 5 - 2 + 2 + 5 + 1 - 9 + 4

解题过程

其实今天的过程还挺曲折的···主要是脑子傻傻的···啥也别说一看到,直接先上两重循环

class Solution:
	def canThreePartsEqualSum(self, A: List[int]) -> bool:
        # time out
        for i in range(1, len(A) - 1):
            for j in range(i + 1, len(A)):
                part1 = sum(A[:i])
                part2 = sum(A[i:j])
                part3 = sum(A[j:len(A)])
                if (part1 == part2) and (part2 == part3):
                    return True
        return False

妥妥的超时了,hhh。双重循环妥妥地时间复杂度 O ( log ⁡ n 2 ) O(\log n^2) O(logn2)啊。

接着想到了,每次对比part,首先得每个part都等于总和的 1 / 3 1/3 1/3,而后面两部份也要确认都等于总和的 1 / 3 1/3 1/3,那就联想到了迭代函数,于是改成以下代码:

class Solution:
	# time:6956ms, beat 5.21%
    # memory 18.6MB, beat 98.29%
    def canTwoPartsEqualSum(self, A: List[int], possibleSum):
        for i in range(1, len(A)):
            part1 = sum(A[:i])
            if part1 == possibleSum:
                if sum(A[i:]) == possibleSum:
                    return True

        return False

    def canThreePartsEqualSum(self, A: List[int]) -> bool:
        possibleSum = sum(A) / 3
        for i in range(1, len(A) - 1):
            if sum(A[:i]) == possibleSum:
                if self.canTwoPartsEqualSum(A[i:], possibleSum):
                    return True

        return False

成功运行,但此时还是非常耗时,为啥?看看上面的代码,时间复杂度其实还是 O log ⁡ ( n 2 ) O\log(n^2) Olog(n2)啊!继续改,首先抛弃迭代函数,直接双层for循环上手,不过先对比了一下第一part的结果,依旧很耗时,因为时间复杂度仍然是 O log ⁡ ( n 2 ) O\log(n^2) Olog(n2)

首先想办法把时间复杂度降下来,怎么做呢?其实可以发现,for循环时第二层for循环是很没必要的,它一定会在第一part满足 1 / 3 1/3 1/3才开始,所以压根不需要这次循环,对整个列表也只需要遍历一次,我们可以用while代替for循环。还有一个问题,假如整个列表的和不能整除3,其实就不需要判断了,直接返回False。于是代码改为:

class Solution:
    def canThreePartsEqualSum(self, A: List[int]) -> bool:
        # time:7284ms, beat 5.21%
        # memory: 18.4MB, beat 98.29%
        if sum(A) % 3:
            return False
        
        possibleSum = sum(A) // 3
        i = 1
        while i < len(A) - 1:
            if sum(A[:i]) == possibleSum:
                break
            i += 1
            if i == len(A) - 1:
                return False

        j = i + 1
        while j < len(A):
            if sum(A[i:j]) == possibleSum:
                return True
            j += 1

        return False

运行成功了,但时间还是很长很长。仔细品品,为啥都while遍历列表了,还蠢蠢地用sum()···

最终改为:

class Solution:
    def canThreePartsEqualSum(self, A: List[int]) -> bool:
        # time:72ms, beat 96.60%
        # memory: 18.8MB, beat 98.29%
        if sum(A) % 3:
            return False
        
        possibleSum = sum(A) // 3
        i = 0
        part1 = 0
        while i < len(A) - 2:
            part1 += A[i]
            i += 1
            if part1 == possibleSum:
                break
            if i == len(A) - 2:
                return False

        part2 = 0
        while i < len(A) - 1:
            part2 += A[i]
            if part2 == possibleSum:
                return True
            i += 1
        return False

运行结果:

执行用时 :72 ms, 在所有 Python3 提交中击败了96.60%的用户
内存消耗 :18.8 MB, 在所有 Python3 提交中击败了98.29%的用户

在这里插入图片描述

【数据库】176. 第二高的薪水

题目

编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。
±—±-------+
| Id | Salary |
±—±-------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
±—±-------+
例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。
±--------------------+
| SecondHighestSalary |
±--------------------+
| 200 |
±--------------------+

解决办法

# Write your MySQL query statement below
SELECT 
IFNULL((SELECT DISTINCT Salary FROM Employee
    ORDER by Salary DESC
    LIMIT 1 OFFSET 1),
    null
) AS SecondHighestSalary;

以上LIMIT n代表查询结果返回前n条数据,OFFSET n表示跳过n条数据。所以LIMIT x OFFSET y就是跳过y条数据,然后再返回前x条数据。以上也可以用LIMIT y, x来替换LIMIT x OFFSET yIFNULL( , )根据字面意思,其实就是如果查询不到,就返回null
撒花~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值