每日LeetCode力扣(16~20)

148 阅读4分钟

16. 最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。
 返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
提示:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4
  • 解题
fun _0016_threeSumClosest() {
    println("--------_0016_threeSumClosest-------")
    println(threeSumClosest(intArrayOf(-1, 2, 1, -4), 1))
    println(threeSumClosest(intArrayOf(-1, -2, 2, 1, -4), 1))
    println(threeSumClosest(intArrayOf(2, 1, -4), 1))
}

fun threeSumClosest(nums: IntArray?, target: Int): Int {
    if (nums == null || nums.size < 3) return 0
    var result = nums[0] + nums[1] + nums[2]
    Arrays.sort(nums)
    for (i in 0..nums.size - 2) {
        var start = i + 1
        var end = nums.size - 1
        while (start < end) {
            val sum = nums[i] + nums[start] + nums[end]
            if (sum > target) {
                end--
            } else {
                start++
            }
            if (abs(sum - target) < abs(result - target)) {
                result = sum
            }
        }
    }
    return result
}

17. 电话号码的字母组合(九宫格键盘)

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
  • 解题
fun _0017_letterCombinations() {
    println("--------_0017_letterCombinations-------")
    println(letterCombinations("23"))
    println(letterCombinations("13"))
    println(letterCombinations("333"))
}

/**
 * 在遍历 digits 中所有的数字时,先建立一个临时的字符串数组t,通过数字到 dict 中取出字符串 str,
 * 然后遍历取出字符串中的所有字符,再遍历当前结果 res 中的每一个字符串,将字符加到后面,并加入到临时字符串数组t中。
 * 取出的字符串 str 遍历完成后,将临时字符串数组赋值给结果 res,具体实现参见代码如下:
 */
fun letterCombinations(digits: String?): ArrayList<String> {
    if (digits == null || digits.isEmpty()) return ArrayList()
    val dict = arrayListOf("0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz")
    var res = arrayListOf("")
    for (i in digits.indices) {
        val t = ArrayList<String>()
        val str = dict[digits[i] - '0']
        for (j in str.indices) {
            for (s in res) {
                t.add(s + str[j])
            }
        }
        res = t
    }
    return res
}

18. 四数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 ab,c 和 d ,
 使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[[-1,  0, 0, 1],
[-2, -1, 1, 2],
[-2,  0, 0, 2]
]
  • 解题
fun _0018_fourSum() {
    println("--------_0018_fourSum-------")
    println(fourSum(intArrayOf(1, 0, -1, 0, -2, 2), 0))
}

fun fourSum(nums: IntArray?, target: Int): List<List<Int>> {
    if (nums == null || nums.size < 4) return ArrayList()
    val res = ArrayList<List<Int>>()
    val n = nums.size
    Arrays.sort(nums)
    for (i in 0..n - 3) {
        if (i > 0 && nums[i] == nums[i - 1]) continue
        for (j in i + 1..n - 2) {
            if (j > i + 1 && nums[j] == nums[j - 1]) continue
            var left = j + 1
            var right = n - 1
            while (left < right) {
                val sum = nums[i] + nums[j] + nums[left] + nums[right]
                if (sum == target) {
                    val oneResult = arrayListOf(nums[i], nums[j], nums[left], nums[right])
                    res.add(oneResult)
                    while (left < right && nums[left] == nums[left + 1]) left++
                    while (left < right && nums[right] == nums[right - 1]) right--
                    left++
                    right--
                } else if (sum < target) {
                    left++
                } else right--
            }
        }
    }
    return res
}

19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗
  • 解题
fun _0019_removeNthFromEnd() {
    println("--------_0019_removeNthFromEnd-------")
    removeNthFromEnd(ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5))))), 1)?.print()
    removeNthFromEnd(ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5))))), 2)?.print()
    removeNthFromEnd(ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5))))), 3)?.print()
    removeNthFromEnd(ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5))))), 4)?.print()
    removeNthFromEnd(ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5))))), 5)?.print()

}

/**
 * 这道题让我们移除链表倒数第N个节点,限定n一定是有效的,即n不会大于链表中的元素总数。
 * 还有题目要求一次遍历解决问题,那么就得想些比较巧妙的方法了。比如首先要考虑的时,如何找到倒数第N个节点,
 * 由于只允许一次遍历,所以不能用一次完整的遍历来统计链表中元素的个数,而是遍历到对应位置就应该移除了。
 * 那么就需要用两个指针来帮助解题,pre 和 cur 指针。首先 cur 指针先向前走N步,如果此时 cur 指向空,
 * 说明N为链表的长度,则需要移除的为首元素,那么此时返回 head->next 即可,如果 cur 存在,再继续往下走,
 * 此时 pre 指针也跟着走,直到 cur 为最后一个元素时停止,此时 pre 指向要移除元素的前一个元素,
 * 再修改指针跳过需要移除的元素即可
 */
fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
    if (head?.next == null) return null
    var n = n
    var pre = head
    var cur = head
    for (i in 0 until n) {
        cur = cur?.next
    }
    if (cur == null) return head.next //说明n为链表长度
    while (cur?.next != null) {
        cur = cur.next
        pre = pre?.next
    }
    pre?.next = pre?.next?.next
    return head
}

20. 有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
  • 解题
fun _0020_isValid() {
    println("--------_0020_isValid-------")
    println(isValid("()"))
    println(isValid("()[]{}"))
    println(isValid("(]"))
    println(isValid("{[]}"))
}

/**
 * 这里需要用一个栈,开始遍历输入字符串,如果当前字符为左半边括号时,则将其压入栈中,如果遇到右半边括号时,
 * 若此时栈为空,则直接返回 false,如不为空,则取出栈顶元素,若为对应的左半边括号,则继续循环,反之返回 false,代码如下:
 */
fun isValid(s: String): Boolean {
    val stack = Stack<Char>()
    for (i in s.indices) {
        val c = s[i]
        if (c == '(' || c == '{' || c == '[')
            stack.push(c)
        else {
            if (stack.isEmpty()) return false
            if (c == ')' && stack.peek() != '(') return false
            if (c == ']' && stack.peek() != '[') return false
            if (c == '}' && stack.peek() != '{') return false
            stack.pop()
        }
    }
    return stack.isEmpty()
}

我是今阳,如果想要进阶和了解更多的干货,欢迎关注公众号”今阳说“接收我的最新文章