LeetCode腾讯精选50题---16,20,21

Day04

16. 最接近的三数之和 (Medium)

16. 最接近的三数之和 (Medium)
思路:此题思路与第十五题差不多,排序+双指针。

  1. 先对数组进行排序;
  2. 设置最大默认值res,目的是趋于最近的target并一直更新;
  3. 固定i,设立双指针left,right分别指向i+1和len(nums) - 1;
  4. 判断abs(sum - target) < abs(res - target),说明sum接近target,并更新res;
  5. 接下来对sum和target进行比较,因为数组是排序后的:若sum<target则左指针left+1向右移动;若sum>target,则右指针right-1向左移动,若sum=target则直接返回target.
"""
    给定一个包括 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^
"""
from typing import List


class Solution(object):
    # 排序+双指针,类似第十五题
    # Time complexity: O(N^2)
    # Space complexity: O(1)
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """

        nums = sorted(nums)
        # 设置最大默认值,趋于最近的和并一直更新
        res = float('inf')

        for i in range(len(nums)):
            # 固定i,并判断是否重复
            if i > 0 and nums[i] == nums[i - 1]:
                continue

            # 设置左右双指针
            left, right = i + 1, len(nums) - 1
            while left < right:
                sum = nums[i] + nums[left] + nums[right]
                # 判断abs(sum - target) < abs(res - target),说明sum接近target,并更新res
                if abs(sum - target) < abs(res - target):
                    res = sum
                if sum < target:
                    left += 1
                elif sum > target:
                    right -= 1
                else:
                    return target

        return target
20. 有效的括号 (Easy)

20. 有效的括号 (Easy)
思路:利用栈的特点(先进后出),见图stack.在这里插入图片描述

图stack
  1. 首先,遍历字符串把所有左括号({[都放进栈里面;
  2. 然后若不是左括号的时候,此时从栈里剔除第一个括号,这里的第一个括号是最近进入的括号,并不是第一个进入栈的括号,即图stack的8
  3. 此时需要检查栈里长度是否为0,若为0则说明只有右括号,因为栈里没有左括号与之匹配;
  4. 若栈里长度不为0,依次判断是否互相匹配,即()、[]、{};
  5. 当遍历完以后,仍然没有产生结果,则检查栈里长度是否为0,若为0则说明已经全部完成匹配,否则说明还有左括号,返回False。
"""
    给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

    有效字符串需满足:
    左括号必须用相同类型的右括号闭合。
    左括号必须以正确的顺序闭合。
    注意空字符串可被认为是有效字符串。

    示例 1:
    输入: "()"
    输出: true

    示例 2:
    输入: "()[]{}"
    输出: true

    示例 3:
    输入: "(]"
    输出: false

    示例 4:
    输入: "([)]"
    输出: false

    示例 5:
    输入: "{[]}"
    输出: true
"""


class Solution_stack(object):
    # 思路:栈方法,特点先进后出
    # Time complexity: O(N)
    # Space complexity: O(N)
    def isValid(self, s: str) -> bool:
        """
        :type s: str
        :rtype: bool
        """
        
        if len(s) == 0:
            return True
        # 建立栈
        stack = []
        
        for i in s:
            # 遍历s,如果所有括号以左边为括号都全部加入到栈里面去
            if i == '(' or i == '{' or i == '[':
                stack.append(i)
            else:
                # 否则的话,先判断此时栈长度是否为0,如果栈为0,那说明此时i为单独的右括号)}],即不会产生配对,不满足有效字符串,返回False
                if len(stack) == 0:
                    return False
                else:
                    # 若此时栈长度不为0,则先把栈元素提出来temp,栈的特点先进后出.此时依次判断i与temp是否配对即可
                    temp = stack.pop()
                    if i == ')':
                        if temp != '(':
                            return False
                    elif i == '}':
                        if temp != '{':
                            return False
                    elif i == ']':
                        if temp != '[':
                            return False
        # 若此时遍历完以后,都没有产生结果,则去判断栈里是否有字符串,有则说明还有左括号({[没有配对返回False,没有则说明全部配对完成返回True
        return True if len(stack) == 0 else False


if __name__ == '__main__':
    s1 = Solution_stack()
    s = "()[]{}"
    print(s1.isValid(s))
21. 合并两个有序链表 (Easy)

21. 合并两个有序链表 (Easy)
思路:此题为链表LinkList的题

在这里插入图片描述

  • 迭代法

    1. leetcode第二题一样,链表的题,定义cur为可移动的result;
    2. 若l1.val <= l2.val,此时cur.next指向l1.val,然后l1往后移l1 = l1.next;
    3. 反之cur.next指向l2.val,然后l2往后移l2 = l1.next;
    4. 当l1或者l2位None,以l1:[1,2,3]和l2:[1,4,5]为例,当while循环进行完毕以后,整个过程是cur = cur.next 1->1->2>->3.此时l1.next为None了,跳出循环,cur = cur.next下一个指向l2的->4->5.
  • 递归法

    1. 设定递归的终止条件;
    2. 同样的以l1:[1,2,3]和l2:[1,4,5]为例,当l1.val <= l2.val的时候,进行递归;
    3. 此时l1.val <= l2.val,l1指向l1.next,即剩下l1:[2,3]和l2:[1,4,5]进行递归;
    4. 此时l1.val > l2.val,l2指向l2.next,即剩下l1:[2,3]和l2:[4,5]进行递归;
    5. 此时l1.val < l2.val,l1指向l1.next,即剩下l1:[3]和l2:[4,5]进行递归;
    6. 此时l1.val < l2.val,l1指向l1.next,l2:[4,5]进行递归,跳出递归返回l2;
"""
    将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

    见图21_Merge_Two_Sorted_Lists.png
    示例 1:
    输入:l1 = [1,2,4], l2 = [1,3,4]
    输出:[1,1,2,3,4,4]

    示例 2:
    输入:l1 = [], l2 = []
    输出:[]

    示例 3:
    输入:l1 = [], l2 = [0]
    输出:[0]

    提示:
    两个链表的节点数目范围是 [0, 50]
    -100 <= Node.val <= 100
    l1 和 l2 均按 非递减顺序 排列
"""


# Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution_iteration:
    # 思路:迭代法
    # Time complexity: O(N)
    # Space complexity: O(N)
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        """
        :type l1: ListNode[1,2,3]
        :type l2: ListNode[1,4,5]
        :rtype: ListNode
        """

        res = ListNode()
        # 与leetcode第二题一样,链表的题,定义cur为可移动的result
        cur = res

        while l1 != None and l2 != None:
            # 若l1.val <= l2.val,此时cur.next指向l1.val,然后l1往后移l1 = l1.next
            if l1.val <= l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                # 反之cur.next指向l2.val,然后l2往后移l2 = l1.next
                cur.next = l2
                l2 = l2.next
            cur = cur.next
        # 当l1或者l2位None,以l1:[1,2,3]和l2:[1,4,5]为例,当while循环进行完毕以后,整个过程是cur = 1->1->2>->3.
        # 此时l1.next为None了,跳出循环,cur = cur.next下一个指向l2的->4->5.
        cur.next = l1 or l2
        return res.next


class Solution_recursion:
    # 思路:递归法
    # Time complexity: O(M+N)
    # Space complexity: O(M+N)
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        """
        :type l1: ListNode[1,2,3]
        :type l2: ListNode[1,4,5]
        :rtype: ListNode
        """

        # 设定递归的终止条件
        if l1 == None or l2 == None:
            return l1 or l2

        # 同样的以l1:[1,2,3]和l2:[1,4,5]为例,当l1.val <= l2.val的时候,进行递归.
        # 1.此时l1.val <= l2.val,l1指向l1.next,即剩下l1:[2,3]和l2:[1,4,5]进行递归;
        # 2.此时l1.val > l2.val,l2指向l2.next,即剩下l1:[2,3]和l2:[4,5]进行递归;
        # 3.此时l1.val < l2.val,l1指向l1.next,即剩下l1:[3]和l2:[4,5]进行递归;
        # 4.此时l1.val < l2.val,l1指向l1.next,l2:[4,5]进行递归,跳出递归返回l2;
        if l1.val <= l2.val:
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1, l2.next)
            return l2

参考资料
BiliBili爱学习的饲养员

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值