Leetcode题121/122/167/169/189/217/219/268/283,Python多种解法(二)

前文

  继上一篇:leetcode题1/26/27/35/53/66/88/118/119已过去了一周,这次接着分享数组前300的easy题,话不多说,直接上题。

121. Best Time to Buy and Sell Stock

class Solution:
    """
    卡登算法,维护当前的最小值和截止目前的利润最大值,这样随着遍历就能找到截止目前的最大值
    Runtime: 40 ms, faster than 99.90% of Python3 online submissions for Best Time to Buy and Sell Stock.
    """
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        min_profit = float("inf")
        tonow_max_profit = 0
        for i in prices:
            if i < min_profit:
                min_profit = i
            if i-min_profit > tonow_max_profit:
                tonow_max_profit = i - min_profit
        return tonow_max_profit


class Solution:
    """
    正常思路的优化,正常思路就是双重循环,代码做了2个优化,第1个是在第二次while的时候增加prices[i]-prices[j]>0的判断,
    可在当找到更小值时直接结束循环;第2个优化是在第一个while的if下i=j,这样虽然是双重循环,但因为i=j的骚操作,实际上也变成了
    单层循环。
    Runtime: 40 ms, faster than 99.90% of Python3 online submissions for Best Time to Buy and Sell Stock.
    """
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        i = j = maxjsum = 0
        n = len(prices)
        while i < n-1:
            if prices[i] < prices[i+1]:
                j = i + 1
                while j < n and prices[j]-prices[i] > 0:
                    if prices[j] - prices[i] > 0:
                        maxjsum = max(maxjsum, prices[j]-prices[i])
                        j += 1
                i = j
            else:
                i += 1
        return maxjsum

122. Best Time to Buy and Sell Stock II



class Solution:
    """
    这道题就是典型的贪心算法:即每次都取当前的最佳结果
    对应到题目就是:一有利益就卖出,最后累计的结果即是最终结果
    因为不能当天买入和卖出,所以每买进一个,如果有收益就卖出,这样才能不断地买进卖出
    Runtime: 40 ms, faster than 99.86% of Python3 online submissions for Best Time to Buy and Sell Stock II.
    """
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        res = 0
        for index,value in enumerate(prices[1:],1):
            if value > prices[index-1]:
                res += value - prices[index-1]
        return res

167. Two Sum II - Input array is sorted

class MySolution:
    """
    这道题采用的解法和第一题Two Sum是一模一样的,唯一不同的是题目要求从1开始计数,所以在返回值上各加了一
    Runtime: 36 ms, faster than 99.77% of Python3 online submissions for Two Sum II - Input array is sorted.
    """
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        res_dict = {}
        for index,value in enumerate(numbers):
            sub = target - value
            if sub in res_dict:
                return [res_dict[sub]+1, index+1]
            else:
                res_dict[value] = index


class Solution:
    """
    讨论区看到的Two-pointer的解法,看起来很棒,因为是有序,所以计算第一个和最后一个的和,如果>target则说明后一个数大了,那就往前推移;
    如果小了,说明前一个数小了,那就往后推移;直到找到那个值;当然也有二分法,但我觉得这道题没必要用二分法来做。
    Runtime: 36 ms, faster than 99.77% of Python3 online submissions for Two Sum II - Input array is sorted.
    """
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        l, r = 0, len(numbers)-1
        while l < r:
            s = numbers[l] + numbers[r]
            if s == target:
                return [l+1, r+1]
            elif s < target:
                l += 1
            else:
                r -= 1

169. Majority Element


class MySolution:
    """
    先投机取巧用python的计数器counter来做,通过most_common去到值最多的1个[()],然后通过索引定位到元素
    Runtime: 48 ms, faster than 94.33% of Python3 online submissions for Majority Element.
    """
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        from collections import Counter
        c = Counter(nums)
        return c.most_common(1)[0][0]

class MySolution2:
    """
    这是除了Counter外自己想的比较笨拙的方法,通过字典存在就给值+1的方法来捕获,然后判断值是否大于n/2就ok了
    Runtime: 60 ms, faster than 59.69% of Python3 online submissions for Majority Element.
    """
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 1:
            return nums[0]
        res_dict = {}
        for i in nums:
            if i in res_dict:
                res_dict[i] += 1
                if res_dict[i] > len(nums)//2:
                    return i
            else:
                res_dict[i] = 1

189. Rotate Array


class MySolution:
    """
    我的解决方法就是通常想到的,通过循环,每一次把最后的数插入到最前方。当然效率也是很慢的,达到132ms
    Runtime: 132 ms, faster than 22.71% of Python3 online submissions for Rotate Array.
    """
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        index = -1
        while index >= -k:
            nums.insert(0, nums.pop())
            index -= 1

class Solution:
    """
    讨论区看的答案,还是被惊艳到了,直接对nums进行三次颠倒就行了,相当于从宏观来考虑
    不过需要补上k取余,因为会给出k的值大于nums的length情况
    Runtime: 44 ms, faster than 100.00% of Python3 online submissions for Rotate Array.
    """
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)
        nums[:-k] = nums[:-k][::-1]
        nums[-k:] = nums[-k:][::-1]
        nums[:] = nums[::-1]

class Solution2:
    """
    可以在上述方法再做优化,直接取一半的数值
    """
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)
        nums[:] = nums[n-k:] + nums[:n-k]

217. Contains Duplicate


class MySolution:
    """
    我的解法很简单,还是从字典入手,如果发现当前值存在字典,则说明超过两次;当然速度就堪忧了。
    Runtime: 48 ms, faster than 80.28% of Python3 online submissions for Contains Duplicate.
    """
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        res_dict = {}
        for i in nums:
            if i not in res_dict:
                res_dict[i] = 0
            else:
                return True
        return False

class MySolution2:
    """
    看到数数就想到python的计数器,我的第二种解法就是利用Counter和它most_common来做
    Runtime: 48 ms, faster than 80.28% of Python3 online submissions for Contains Duplicate.
    """
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        from collections import Counter
        if not len(nums):
            return False
        c = Counter(nums)
        res = c.most_common(1)[0][1]
        return res != 1

class Solution:
    """
    讨论区的一向精简,直接通过set来完成,不得不说从列表中判断数量时set非常好用
    Runtime: 44 ms, faster than 98.12% of Python3 online submissions for Contains Duplicate.
    """
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        return len(set(nums)) != len(nums)

219. Contains Duplicate II


class MySolution:
    """
    我的解法还是利用字典来做,要注意的是当第一轮找到的两个相同的数距离大于k时,要用第二个数的index重置第一个数,继续往下遍历
    Runtime: 48 ms, faster than 88.89% of Python3 online submissions for Contains Duplicate II.
    """
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        res_dict = {}
        for index,value in enumerate(nums):
            if value not in res_dict:
                res_dict[value] = index
            else:
                res = index - res_dict[value]
                if res <= k:
                    return True
                else:
                    res_dict[value] = index
        return False

class Solution:
    """
    看到讨论区的字典解法比我的简单点,不过原理是一样的,mark一下,不过连runtime都比我的好
    Runtime: 44 ms, faster than 97.62% of Python3 online submissions for Contains Duplicate II.
    """
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        dic = {}
        for i, v in enumerate(nums):
            if v in dic and i - dic[v] <= k:
                return True
            dic[v] = i
        return False

268. Missing Number


class MySolution:
    """
    用python的set差集来做,但效率很低
    Runtime: 52 ms, faster than 45.33% of Python3 online submissions for Missing Number.
    """
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums) + 1
        res_list = list(range(n))
        res = set(res_list) - set(nums)
        return list(res)[0]


class Solution:
    """
    讨论区果然还是大神多,用求和的方法轻松拿到答案
    Runtime: 40 ms, faster than 100.00% of Python3 online submissions for Missing Number.
    """
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        return sum(range(len(nums) + 1)) - sum(nums)

283. Move Zeroes


class MySolution:
    """
    思路很简单,定义首尾2个数,如果首部为0就删除首部,然后尾部插入0即可
    Runtime: 44 ms, faster than 100.00% of Python3 online submissions for Move Zeroes.
    """
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        start = 0
        end = len(nums) - 1
        while start < end:
            if nums[start] == 0:
                del nums[start]
                nums.append(0)
                end -= 1
            else:
                start += 1


class Solution:
    """
    讨论区的一种解法直接判断是否为0,是的话就往后交换,
    Runtime: 44 ms, faster than 100.00% of Python3 online submissions for Move Zeroes.
    """
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        zero = 0  # records the position of "0"
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[i], nums[zero] = nums[zero], nums[i]
                zero += 1

总结

  本次记录到此为止,一共九题,多谢观看~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值