【LeetCode】Top100 经典必刷题 03【3/20】

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

 

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1

 

提示:

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104

python 参考题解:

第11道题是 "Container With Most Water",题目描述如下: 给定 n 个非负整数 a1, a2, ..., an,每个数代表一个柱子的高度。 在坐标平面内画 n 个柱子,使得这些柱子的高度分别是 a1, a2, ..., an。 求在这些柱子之间可以接多少水。 说明:

  • 柱子之间可以放置水,且柱子之间可以有多段水相连。
  • 每个柱子只能放置水平的一层水。

示例:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49

以下是用 Python 给出的题解:

def maxArea(height):
    # 初始化两个指针,分别指向数组的开始和结束
    left, right = 0, len(height) - 1
    max_area = 0
    # 遍历数组,每次移动较小的指针
    while left < right:
        # 计算当前两柱子间的面积
        curr_area = (right - left) * min(height[left], height[right])
        # 更新最大面积
        max_area = max(max_area, curr_area)
        # 移动较小的指针
        if height[left] < height[right]:
            left += 1
        else:
            right -= 1
    return max_area
# 示例
print(maxArea([1,8,6,2,5,4,8,3,7]))  # 输出: 49

解题思路和步骤:

  1. 初始化变量:首先,我们初始化两个指针 leftright,分别指向数组的开始和结束。我们还需要一个变量 max_area 来存储最大面积。
  2. 遍历数组:使用一个循环遍历数组 height
  3. 计算当前面积:对于当前的 leftright 指针,计算它们之间的面积。面积等于 (right - left) * min(height[left], height[right])
  4. 更新最大面积:将当前面积与 max_area 进行比较,并更新 max_area 为较大者。
  5. 移动指针:在每次循环中,我们移动较小的指针。如果 height[left] 小于 height[right],则移动 left;否则移动 right
  6. 返回结果:遍历完成后,返回 max_area 作为结果。

这个算法的时间复杂度是 O(n),其中 n 是数组 height 的长度,因为我们只需要遍历数组一次。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。

12. 整数转罗马数字

七个不同的符号代表罗马数字,其值如下:

符号
I1
V5
X10
L50
C100
D500
M1000

罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:

  • 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  • 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
  • 只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式

给定一个整数,将其转换为罗马数字。

 

示例 1:

输入:num = 3749

输出: "MMMDCCXLIX"

解释:

3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M)
 700 = DCC 由于 500 (D) + 100 (C) + 100 (C)
  40 = XL 由于 50 (L) 减 10 (X)
   9 = IX 由于 10 (X) 减 1 (I)
注意:49 不是 50 (L) 减 1 (I) 因为转换是基于小数位

示例 2:

输入:num = 58

输出:"LVIII"

解释:

50 = L
 8 = VIII

示例 3:

输入:num = 1994

输出:"MCMXCIV"

解释:

1000 = M
 900 = CM
  90 = XC
   4 = IV

 

提示:

  • 1 <= num <= 3999

python 参考题解:

第12道题是 "Integer to Roman",题目描述如下: 将一个整数转换为其罗马数字表示形式。

示例 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.

以下是用 Python 给出的题解:

def intToRoman(num):
    val = [
        1000, 900, 500, 400,
        100, 90, 50, 40,
        10, 9, 5, 4,
        1
        ]
    syb = [
        "M", "CM", "D", "CD",
        "C", "XC", "L", "XL",
        "X", "IX", "V", "IV",
        "I"
        ]
    roman_num = ''
    i = 0
    while  num > 0:
        for _ in range(num // val[i]):
            roman_num += syb[i]
            num -= val[i]
        i += 1
    return roman_num
# 示例
print(intToRoman(3))  # 输出: "III"
print(intToRoman(4))  # 输出: "IV"
print(intToRoman(9))  # 输出: "IX"
print(intToRoman(58)) # 输出: "LVIII"
print(intToRoman(1994)) # 输出: "MCMXCIV"

解题思路和步骤:

  1. 初始化变量:首先,我们定义两个列表 valsybval 列表包含罗马数字的值,syb 列表包含对应的符号。
  2. 创建罗马数字字符串:使用一个循环,遍历 val 列表中的每个值。
  3. 计算当前值:对于每个值,我们计算当前数字可以转换成多少个该值。
  4. 添加罗马数字符号:将计算出的个数乘以对应的罗马数字符号,并添加到罗马数字字符串中。
  5. 更新数字:每次添加完符号后,我们从原始数字中减去相应的值。
  6. 返回结果:循环结束后,返回罗马数字字符串。

这个算法的时间复杂度是 O(n),其中 n 是数字的位数,因为我们只需要遍历数字一次。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。

13. 罗马数字转整数

罗马数字包含以下七种字符: I, V, X, LCD 和 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:

输入: s = "III"
输出: 3

示例 2:

输入: s = "IV"
输出: 4

示例 3:

输入: s = "IX"
输出: 9

示例 4:

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.

示例 5:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

 

提示:

  • 1 <= s.length <= 15
  • s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
  • 题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999]
  • 题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
  • IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
  • 关于罗马数字的详尽书写规则,可以参考 罗马数字 - 百度百科

python 参考题解:

第13道题是 "Roman to Integer",题目描述如下: 给定一个罗马数字,将其转换为整数。

示例 1:

输入: "III"
输出: 3

示例 2:

输入: "IV"
输出: 4

示例 3:

输入: "IX"
输出: 9

示例 4:

输入: "LVIII"
输出: 58

示例 5:

输入: "MCMXCIV"
输出: 1994

以下是使用Python编写的解题代码:

def romanToInt(s: str) -> int:
    roman_to_int_map = {
        "I": 1,
        "IV": 4,
        "V": 5,
        "IX": 9,
        "X": 10,
        "XL": 40,
        "L": 50,
        "XC": 90,
        "C": 100,
        "CD": 400,
        "D": 500,
        "CM": 900,
        "M": 1000
    }
    
    # 初始化结果为0
    result = 0
    
    # 遍历罗马数字字符串
    for i in range(0, len(s), 2):
        # 如果当前位置是罗马数字的结尾,则直接添加到结果中
        if i + 1 == len(s):
            result += roman_to_int_map[s[i]]
            break
        
        # 当前罗马数字和下一个罗马数字的组合
        combo = s[i:i+2]
        
        # 如果组合存在,则添加到结果中
        if combo in roman_to_int_map:
            result += roman_to_int_map[combo]
        else:
            # 否则,添加当前罗马数字到结果中
            result += roman_to_int_map[s[i]]
            
    return result
# 示例
print(romanToInt("III"))  # 输出: 3
print(romanToInt("IV"))  # 输出: 4
print(romanToInt("IX"))  # 输出: 9
print(romanToInt("LVIII"))  # 输出: 58
print(romanToInt("MCMXCIV"))  # 输出: 1994

解题思路和步骤:

  1. 初始化变量:首先,我们定义一个字典 roman_to_int_map,用于存储罗马数字及其对应的整数值。
  2. 初始化结果:创建一个变量 result 并初始化为0,用于存储转换后的整数值。
  3. 遍历罗马数字字符串:使用一个循环遍历罗马数字字符串 s。由于罗马数字的组合特性,我们每次可以处理两个字符,因此循环步长为2。
  4. 处理组合罗马数字:如果当前位置是罗马数字的结尾,则直接将该罗马数字添加到结果中。否则,检查当前位置和下一个位置的罗马数字组合是否存在于 roman_to_int_map 中,如果是,则添加到结果中;否则,只添加当前位置的罗马数字到结果中。
  5. 返回结果:循环结束后,返回 result 作为转换后的整数值。

这个算法的时间复杂度是 O(n),其中 n 是罗马数字字符串的长度,因为我们只需要遍历字符串一次。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。

14. 最长公共前缀

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

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

 

示例 1:

输入:strs = ["flower","flow","flight"]
输出:"fl"

示例 2:

输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。

 

提示:

  • 1 <= strs.length <= 200
  • 0 <= strs[i].length <= 200
  • strs[i] 仅由小写英文字母组成

python 参考题解:

第14道题是 "Longest Common Prefix",题目描述如下: 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。

示例 1:

输入: ["flower","flow","flight"]
输出: "fl"

示例 2:

输入: ["dog","racecar","car"]
输出: ""

以下是使用Python编写的解题代码:

def longestCommonPrefix(strs):
    if not strs:
        return ""
    
    # 获取最短字符串,以它作为基准
    min_str = min(strs, key=len)
    
    # 遍历基准字符串,寻找最长公共前缀
    for i, char in enumerate(min_str):
        # 遍历其他字符串,检查当前字符是否相同
        for other_str in strs:
            if other_str[i] != char:
                return min_str[:i]
    
    return min_str
# 示例
print(longestCommonPrefix(["flower","flow","flight"]))  # 输出: "fl"
print(longestCommonPrefix(["dog","racecar","car"]))     # 输出: ""

解题思路和步骤:

  1. 边界情况处理:首先,如果字符串数组 strs 为空,直接返回空字符串。
  2. 获取最短字符串:使用 Python 的 min 函数和 key 参数,获取字符串数组中的最短字符串,作为基准字符串。
  3. 遍历基准字符串:使用一个循环遍历基准字符串的每一个字符。
  4. 检查当前字符:在循环中,我们检查基准字符串的当前字符是否在所有其他字符串中都有相同的字符。
  5. 返回公共前缀:如果当前字符在所有其他字符串中都有相同的字符,继续遍历;如果当前字符在某个字符串中不同,则返回基准字符串中当前字符之前的所有字符。
  6. 返回结果:循环结束后,返回基准字符串作为最长公共前缀。

这个算法的时间复杂度是 O(n * m),其中 n 是字符串数组的长度,m 是基准字符串的长度。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。

15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

 

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

 

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

python 参考题解:

第15道题是 "3Sum",题目描述如下: 给定一个包含 n 个整数的数组 `nums`,判断 `nums` 中是否存在三个元素 `a, b, c` 使得 `a + b + c = 0`?找出所有满足条件且不重复的三元组。

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

示例 1:

输入: [-1, 0, 1, 2, -1, -4]
输出: [
  [-1, -1, 2],
  [-1, 0, 1]
]

以下是使用Python编写的解题代码:

def threeSum(nums):
    # 首先对数组进行排序
    nums.sort()
    result = []
    
    # 遍历数组,固定一个元素
    for i in range(len(nums) - 2):
        # 跳过重复的元素
        if i > 0 and nums[i] == nums[i - 1]:
            continue
        # 遍历剩余的元素,固定第二个元素
        left, right = i + 1, len(nums) - 1
        while left < right:
            # 计算当前三数之和
            total = nums[i] + nums[left] + nums[right]
            # 如果三数之和等于0,添加到结果中
            if total == 0:
                result.append([nums[i], nums[left], nums[right]])
                # 跳过重复的元素
                while left < right and nums[left] == nums[left + 1]:
                    left += 1
                while left < right and nums[right] == nums[right - 1]:
                    right -= 1
                left += 1
                right -= 1
            # 如果三数之和大于0,移动右指针
            elif total > 0:
                right -= 1
            # 如果三数之和小于0,移动左指针
            else:
                left += 1
                
    return result
# 示例
print(threeSum([-1, 0, 1, 2, -1, -4]))  # 输出: [[-1, -1, 2], [-1, 0, 1]]

解题思路和步骤:

  1. 排序数组:首先,我们对输入的数组 nums 进行排序,以便后续操作。
  2. 遍历数组:使用一个循环遍历数组,固定第一个元素。
  3. 跳过重复元素:在循环中,我们跳过重复的元素,以避免重复的三元组。
  4. 使用双指针:对于每个固定元素,我们使用双指针 leftright 来寻找另外两个元素,使得三数之和等于0。
  5. 添加结果:如果找到满足条件的三元组,我们将其添加到结果列表中。
  6. 返回结果:遍历完成后,返回结果列表。

这个算法的时间复杂度是 O(n^2),因为我们需要对数组进行排序,并且对于每个元素,我们都需要使用双指针来寻找其他两个元素。空间复杂度是 O(n),因为我们需要存储结果列表。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值