每日LeetCode力扣(11~15)

95 阅读1分钟

11. 盛最多水的容器

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。
在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器
示例 1:
输入:height =[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
示例 3:
输入:height = [4,3,2,1,4]
输出:16
示例 4:
输入:height = [1,2,1]
输出:2
提示:
n = height.length
2 <= n <= 3 * 104
0 <= height[i] <= 3 * 104
  • 解题
fun _0011_maxArea() {
    println("--------_011_maxArea-------")
    println(maxArea(intArrayOf(1, 8, 6, 2, 5, 4, 8, 3, 7)))
    println(maxArea(intArrayOf(1, 1)))
    println(maxArea(intArrayOf(4, 3, 2, 1, 4)))
    println(maxArea(intArrayOf(1, 2, 1)))
    println(maxArea(intArrayOf(4, 3, 9, 1, 1, 9, 2, 1)))
}

/**
 * 定义i和j两个变量分别指向数组的左右两端,然后两个指针向中间搜索,
 * 每移动一次算一个值和结果比较取较大的,
 * 容器装水量的算法是找出左右两个边缘中较小的那个乘以两边缘的距离,
 * 对于相同的高度们直接移动i和j就行了,不再进行计算容量了
 */
fun maxArea(height: IntArray): Int {
    var res = 0
    var i = 0
    var j = height.size - 1
    while (i < j) {
        val h = Math.min(height[i], height[j])
        res = Math.max(res, h * (j - i))
        while (i < j && h == height[i]) ++i
        while (i < j && h == height[j]) --j
    }
    return res
}

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 的范围内。
示例 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.
  • 解题
fun _0012_intToRoman() {
    println("--------_012_intToRoman-------")
    println(intToRoman(3))
    println(intToRoman(4))
    println(intToRoman(9))
    println(intToRoman(58))
    println(intToRoman(49))
    println(intToRoman(444))
    println(intToRoman(555))
    println(intToRoman(666))
    println(intToRoman(888))
    println(intToRoman(999))
    println(intToRoman(1994))
    println(intToRoman(3999))
}

/**
 * 本题由于限制了输入数字范围这一特殊性,故而有一种利用贪婪算法的解法,
 * 建立一个数表,每次通过查表找出当前最大的数,减去再继续查表
 */
fun intToRoman(num: Int): String {
    print("$num-->")
    var num = num
    val strs = arrayOf("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I")
    val nums = intArrayOf(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
    val result = StringBuffer()
    for (i in nums.indices) {
        while (num >= nums[i]) {
            num -= nums[i]
            result.append(strs[i])
        }
    }
    return result.toString()
}

13. 罗马数字转整数

罗马数字包含以下七种字符: 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.
提示:
题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
IC 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics 。
  • 解题
fun _0013_romanToInt() {
    println("--------_013_romanToInt-------")
    println(romanToInt("III"))
    println(romanToInt("IV"))
    println(romanToInt("IX"))
    println(romanToInt("LVIII"))
    println(romanToInt("XLIX"))
    println(romanToInt("CDXLIV"))
    println(romanToInt("DLV"))
    println(romanToInt("DCLXVI"))
    println(romanToInt("DCCCLXXXVIII"))
    println(romanToInt("CMXCIX"))
    println(romanToInt("MCMXCIV"))
    println(romanToInt("MMMCMXCIX"))

}

/**
需要用到 HashMap 数据结构,来将罗马数字的字母转化为对应的整数值,因为输入的一定是罗马数字,
那么只要考虑两种情况即可:
第一,如果当前数字是最后一个数字,或者之后的数字比它小的话,则加上当前数字。
第二,其他情况则减去这个数字。
 */
fun romanToInt(s: String): Int {
    print("$s-->")
    var s = s
    var res = 0
    val map = mapOf('I' to 1, 'V' to 5, 'X' to 10, 'L' to 50, 'C' to 100, 'D' to 500, 'M' to 1000)
    for (i in s.indices) {
        val t: Int = map.getValue(s[i])
        if (i == s.length - 1 || map.getValue(s[i + 1]) <= map.getValue(s[i])) res += t
        else res -= t
    }
    return res
}

14. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
  • 解题
fun _0014_longestCommonPrefix() {
    println("--------_014_longestCommonPrefix-------")
    println(longestCommonPrefix(arrayOf("flower", "flow", "flight")))
    println(longestCommonPrefix(arrayOf("dog", "racecar", "car")))
}

/**
 * 给输入字符串数组排个序,按字母顺序排序的话,那么有共同字母多的两个字符串会被排到一起,
 * 而跟大家相同的字母越少的字符串会被挤到首尾两端,那么如果有共同前缀的话,一定会出现在首尾两端的字符串中,
 * 所以只需要找首尾字母串的共同前缀即可。
 * 由于是按字母顺序排的,而不是按长度,所以首尾字母的长度关系不知道,为了防止溢出错误,只遍历而这种较短的那个的长度,
 * 找出共同前缀返回即可
 */
fun longestCommonPrefix(strs: Array<String>?): String {
    if (strs == null || strs.isEmpty()) return ""
    Arrays.sort(strs)
    var i = 0
    var len = min(strs[0].length, strs[strs.size - 1].length)
    while (i < len && strs[0][i] == strs[strs.size - 1][i]) {
        i++
    }
    return strs[0].substring(0, i)
}

15. 三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 ab,c ,使得 a + b + c = 0 ?
请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -1,1,-4],
满足要求的三元组集合为:
[[-1, 0, 1],
[-1, -1, 2]
]
  • 解题
fun _0015_threeSum() {
    println("--------_015_threeSum-------")
    println(threeSum(intArrayOf(-1, 0, 1, -2, 2, 2, -1, -1, 1, -4)).toString())
}

fun threeSum(nums: IntArray?): List<List<Int>> {
    if (nums == null || nums.size < 3) return ArrayList()
    Arrays.sort(nums)
    val ret = LinkedList<List<Int>>()
    val set = HashSet<List<Int>>()
    for (i in 0..nums.size - 2) {
        if (i > 0 && nums[i] == nums[i - 1]) continue//对i去重
        var start = i + 1
        var end = nums.size - 1
        while (start < end) {
            if (nums[i] + nums[start] + nums[end] == 0) {
                val oneResult = LinkedList<Int>()
                oneResult.add(nums[i])
                oneResult.add(nums[start])
                oneResult.add(nums[end])
                set.add(oneResult)
                start++
                end--
            } else {
                if (nums[i] + nums[start] + nums[end] < 0) {
                    start++
                } else {
                    end--
                }
            }
        }
    }
    ret.addAll(set)
    return ret
}
我是今阳,如果想要进阶和了解更多的干货,欢迎关注公众号”今阳说“接收我的最新文章