11.盛水最多的容器
给定 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
解法 时间复杂度o(n) 空间复杂度o(1)
假定初始状态是最左边的垂线和最右边的垂线,需要求的值其实是 min(leftValue, rightValue) * (rightPos - leftPos)
如果想要这个面积继续增加,剩下的组合里肯定只能把一边的垂线向中间靠拢,rightPos - leftPos一定是减少的,那么min(leftValue, rightValue)必须增加才有可能增大面积,所以要将比较小的那条线向中间靠拢, 不断移动,计算直到两条垂线重合
11. 整数转罗马数字
略
12. 罗马数字转整数
罗马数字包含以下七种字符: 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 的范围内。
解法 时间复杂度o(n) 空间复杂度o(1)
遍历即可,当遍历到第i个字符的时候,如果i + 1个字符代表的数字,比第i个字符代表的数字大,则说明命中了特殊规则, 先加第i+1字符数字再减第i字符数字即可,否则直接加上第i字符数字
13. 最长字公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
输入: ["flower","flow","flight"]
输出: "fl"
解法 时间复杂度o(n) 空间复杂度O(1)
最外层遍历第一个字符串,内存遍历余下的字符串,如果第一个字符串的位置大于其他任意一个字符串的长度或者其他字符串字符与当前位置不符,跳出循环。最外层循环外返回第一个字符串从0到遍历成功的位置截止的字符串
15. 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解法 时间复杂度o(nlogn + n²) 空间复杂度o(n)
先对输入数组进行排序 时间复杂度nlogn 此时数组是从小到大排序
遍历输入数组 确定选择的的第一个数为当前遍历到的数,而剩下的两个数都在这个数的右边。
先假定剩下的两个数,一个左数是 nums[i+1] 另一个右数是nums[len(nums) - 1],求和,如果求出来的和大于0,则右数需要往左移动以减小计算的和,如果小于0,则左数位置需要往右移动以增加计算的和。如果等于0 则保存此时的三个数, 左数和右数位置同时移动以寻找下一个组合。直到左数和右数位置重合。
无论是最外层的遍历,还是内层的移动左/右数位置,如果发现移动后的位置的数和上一个数一样,跳过后续步骤,继续遍历/移动
此外当 确定的第一个数大于0时 三数之和一定是大于0的,可以直接跳出最外层遍历了。