力扣打卡2

2020 08/05

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i
的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。 图中垂直线代表输入数组
[1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 示例:
输入:[1,8,6,2,5,4,8,3,7] 输出:49

双指针题,这种需要从两端开始往中间遍历得题目,主要是你得能想到是双指针,而且,搞好指针变动的规律,这里就是哪边得低则那边就往另一个方向移动。

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        # 从两端开始,每次固定长边,移动短边,同时那些如果移动后比移动前得边短得边不需要计算容量
        s = 0
        e = len(height) - 1
        maxV = 0
        while s < e:
            save = s
            short = s if height[s] < height[e] else e
            area = height[short] * (e-s)
            maxV = area if area > maxV else maxV
            s = s if height[s] > height[e] else (s+1) 
            e = e if height[e] > height[save] else (e-1)
        return maxV

还可以做一些优化,就是两边指针移动得时候,对于移动后的高度还不如之前的那些边就可以不用去计算面积,与因为长度已经短了,你如果高度还低了,那肯定不会是最大得面积。

2020 08/11

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值 I 1 V 5 X 10 L
50 C 100 D 500 M 1000 例如, 罗马数字 2
写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5
的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示
40 和 90。 C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。 示例 1: 输入: 3 输出: “III” 示例 2: 输入: 4
输出: “IV” 示例 3: 输入: 9 输出: “IX” 示例 4: 输入: 58 输出: “LVIII” 解释: L = 50, V =
5, III = 3. 示例 5: 输入: 1994 输出: “MCMXCIV” 解释: M = 1000, CM = 900, XC =
90, IV = 4.

class Solution(object):
    def intToRoman(self, num):
        """
        :type num: int
        :rtype: str
        """
        roman1 = {1:"I",2:"II",3:"III",4:"IV",5:"V",6:"VI",7:"VII",8:"VIII",9:"IX",10:"X"}
        roman2 = {1:"X",2:"XX",3:"XXX",4:"XL",5:"L",6:"LX",7:"LXX",8:"LXXX",9:"XC",10:"C"}
        roman3 = {1:"C",2:"CC",3:"CCC",4:"CD",5:"D",6:"DC",7:"DCC",8:"DCCC",9:"CM",10:"M"}
        roman4 = {1:"M",2:"MM",3:"MMM"}
        tho = num//1000   # 只会是0,1,2,3
        hun = (num%1000)//100  #  0~9
        ten = (num%100)//10    #  0~9
        sin = num%10           #  0~9
        str_tho = roman4[tho] if tho else ""
        str_hun = roman3[hun] if hun else ""
        str_ten = roman2[ten] if ten else ""
        str_sin = roman1[sin] if sin else ""

        return str_tho + str_hun + str_ten + str_sin

我使用了比较好像的罗列法,快速的罗列 还挺快的,最后执行速度和内存都还行

2020 08/12
p1

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值 I 1 V 5 X 10 L
50 C 100 D 500 M 1000 例如, 罗马数字 2
写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5
的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: I
可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示 40
和 90。 C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。 示例 1: 输入: “III” 输出: 3 示例 2: 输入:
“IV” 输出: 4 示例 3: 输入: “IX” 输出: 9 示例 4: 输入: “LVIII” 输出: 58 解释: L = 50,
V= 5, III = 3. 示例 5: 输入: “MCMXCIV” 输出: 1994 解释: M = 1000, CM = 900, XC
= 90, IV = 4.

class Solution(object):
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        roman = {"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000}
        i = 0
        sum = 0
        while i < len(s):
            if i+1 < len(s):
                if roman[s[i+1]] > roman[s[i]]:
                    sum = sum + roman[s[i+1]] - roman[s[i]]
                    i = i + 2
                else:
                    sum = sum + roman[s[i]]
                    i = i + 1
            else:
                sum = sum + roman[s[i]]
                i = i + 1
        return sum

本质思想:小的在左边肯定是减法,小的在右边就是加法。做个映射 最后相加就行了。

p2

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: [“flower”,“flow”,“flight”] 输出: “fl” 示例 2:

输入: [“dog”,“racecar”,“car”] 输出: “” 解释: 输入不存在公共前缀。 说明:

所有输入只包含小写字母 a-z 。

class Solution(object):
    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """
        max_str = ""
        flag = True
        if len(strs)>1:
            for i in range(len(strs[0])):
                for j in range(len(strs)-1):
                    print(j)
                    if i< len(strs[j+1]) and strs[j+1][i] == strs[0][i]:
                        if j == len(strs[1:])-1:
                            max_str = max_str + strs[j+1][i]
                        else:
                            continue
                    else:
                        flag = False
                        break
                if not flag:
                    break
            return max_str
        else:
            if len(strs) == 1:
                return strs[0]
            else:
                return ""

这里用了暴力解法,速度很慢,只有6%,内存还行85%,去看了看大神的解法:

class Solution(object):
    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """
        if strs:
            count = 0
            for temp in zip(*strs):   # 编程每个对应位置构成一个列表,取最短的,最后拼成一个大列表
                if len(set(temp)) == 1:
                    count = count + 1
                else:
                    break
            max_str = strs[0][:count]
            return max_str
        else:
            return ""

骚操作,利用python的zip函数,将列表迭代成对应位置放一起的列表,最后再放到一起成一个大列表。时间50%。

2020 08/13

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0
?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        results = []
        nums.sort()
        print(nums)
        if len(nums) < 3 or nums[0] > 0 or nums[-1] < 0:
            return []
        else:
            for i in range(len(nums) - 2):
                left = i + 1
                right = len(nums) - 1  # 右指针初始化为最后一个
                if nums[i] > 0:
                    break
                if i > 0 and nums[i] == nums[i - 1]:  # 和前面的一样就不再走下去直接开启下一个循环
                    continue
                while left < right and nums[i] <= 0:
                    if nums[i] + nums[left] + nums[right] == 0:
                        result = []
                        result.append(nums[i])
                        result.append(nums[left])
                        result.append(nums[right])
                        results.append(result)
                        while left < right and nums[left] == nums[left+1]:
                            left = left + 1
                        while left < right and nums[right] == nums[right-1]:
                            right = right - 1
                        left = left + 1
                        right = right - 1

                    elif nums[i] + nums[left] + nums[right] < 0:
                        left = left + 1
                    else:
                        right = right - 1
            return results

首先进行排序,然后利用双指针遍历,第一个数一定是小于0,他大于零,后面肯定不可能相加为0,最右边的肯定也不能小于零,否则也没有。
这就确定了截至条件,然后难点还有去重以及,第二个数的移动。
第二个数也就是left(第一个是i),对于去重,跳过相同的,左右都这么干,最后左右都往前走一步。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值