leetcode hot 100——easy题(python)

题解思路主要来源于@灵茶山艾府。

1 两数之和

1.1 题目

        给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只对应一个答案,但是数组中的同一个元素不能重复出现。你可以按任意顺序返回答案。

示例:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9,返回[0,1]

1.2 思路

        建立一个哈希表,遍历nums数组中的元素,如果target-nums[i]不存在哈希表中,就将nums[i]作为key,i作为value插入到哈希表中。

1.3 代码

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashmap = {}
        for i in range(len(nums)):
            if target - nums[i] in hashmap:
                return [i, hashmap[target-nums[i]]]
            
            hashmap[nums[i]] = i

2 移动零

2.1 题目

        给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。要求在不复制数组的情况下对原数组进行操作。

示例:

输入:nums = [0,1,0,3,12]
输出:[1,3,12,0,0]

2.2 思路

        把0视作空位,将所有元素都移到数组左边的空位:遍历nums数组元素,同时维护一个下标i0,每次遇到nums[i]≠0,就把nums[i]和nums[i0]互换,且i0和i都加1;如果nums[i] = 0,则只需要把i加1.

2.3 代码

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        i0 = 0
        for i in range(len(nums)):
            if nums[i]:
                nums[i], nums[i0] = nums[i0], nums[i]
                i0 += 1     
        

3 相交链表

3.1 题目

        给两个单链表的头结点headA和headB,请找出并返回两个单链表相交的起始节点,如果不存在交点则返回null。题目数据保证链表中无环。函数返回结果后链表的原始结构不变。

示例:

3.2 思路

        定义两个指针p和q,分别从两个单链表出发,不断向后走一步,当p走完headA这个单链表,就继续在headB链表向前走,q也一样。如果p不为空,则更新p为p.next,否则更新p为headB,q也一样。最终如果两个链表有交点,则p=q;如果没有交点,p和q在None处相交。

3.3 代码

# class ListNode:
#    def __init__(self, x):
#        self.val = x
#        self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> optional[ListNode]:
        p,q = headA, headB
        while p is not q:
            p = p.next if p else headB
            q = q.next if q else headA
        return p
        
   

4 反转链表

4.1 题目

        给你单链表的头结点head,请反转链表,并返回反转后的链表。

示例:

4.2 思路

        遍历链表,访问各节点时修改next的指向。

4.3 代码

# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

class Solution:
    def reverseList(self, head: optional[ListNode]) -> optional[ListNode]:
        pre, cur = None, head
        while cur:
            nxt = cur.next
            cur.next = pre
            pre = cur
            cur = nxt
            # 也可以合并为cur.next, pre, cur = pre, cur, cur.next
        return pre

5 环形链表

5.1 题目

        给定一个链表的头结点head,判断链表中是否有环。如果有环,则返回True,否则返回False。

示例:

5.2 思路

        将判断是否有环问题转为龟兔赛跑问题,龟兔同时从头结点出发,乌龟每次前移一格,兔子每次前移两格,如果有环,则龟兔一定会相遇。因此可以定义快慢指针slow和fast,如果最后fast和slow指向同一个节点,则有环,反之没有。

5.3 代码

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: optional[ListNode]) -> bool:
        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if fast is slow:
                return True
        return False

6 回文链表

6.1 题目

        给你一个单链表的头结点head,请你判断该链表是否为回文链表,如果是返回True,否则返回False。

示例:

6.2 思路

        首先找链表head的中间节点mid(如果节点数是奇数,则是正中间节点;如果是偶数,则是正中间右边的节点),然后将mid节点到末尾这段链表翻转得到head2,最后遍历head和head2两个链表,每次循环判断head.val和head2.val是否相等。如果不相等,则返回False;如果直到结束都没返回False,则返回True。

6.3 代码

# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

class Solution:
    # 找中间节点
    def midNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        return slow

    # 反转后半部分链表
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        pre, cur = None, head
        while cur:
            cur.next, pre, cur = pre, cur, cur.next
        return pre

    # 判断回文
    def isPalindrome(self, head: Optional[ListNode]) -> bool:
        mid = self.midNode(head)
        head2 = self.reverseList(mid)
        while head2:
            if head.val != head2.val:
                return False
            head = head.next
            head2 = head2.next
        return True

7 合并两个有序链表

7.1 题目

        将两个升序链表合并成一个新的升序链表,新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

7.2 思路

        递归:如果其中一个链表为空,直接返回另一个链表作为合并后的结果;如果两个链表都不为空,则比较两个链表当前节点的值,并选择较小的节点作为新链表的当前节点。

7.3 代码

class ListNode:
    def __init__(sel, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Opational[ListNode]) -> Optional[ListNode]:
        if list1 is None:
            return list2
        if list2 is None:
            return list1
        if list1.val < list2.val:
            list1.next = self.mergeTwoLists(list1.next, list2)
            return list1
        list2.next = self.mergeTwoLists(list1, list2.next)
        return list2

8 二叉树的前中后序遍历

8.1 题目

        给定一个二叉树的根节点root,返回其中序遍历。

示例:

8.2 思路

        递归,顺序遍历节点

8.3 代码

# class TreeNode:
#    def __init__(self, val=0, left=None, right=None):
#        self.val = val
#        self.left = left
#        self.right = right

class Solution:
    # 前序
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def helper(root):
            if not root:
                return
            res.append(root.val)
            helper(root.left)
            helper(root.right)
        helper(root)
        return res

    # 中序
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def helper(root):
            if not root:
                return
            helper(root.left)
            res.append(root.val)
            helper(root.right)
        helper(root)
        return res

    # 后序
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def helper(root):
            if not root:
                return
            helper(root.left)
            helper(root.right)
            res.append(root.val)
        helper(root)
        return res
    

9 二叉树的最大深度

9.1 题目

        给定一个二叉树root,返回其最大深度(根节点到最远子节点的最长路径上的节点数)。

示例:

9.2 思路

        递归:如果我们知道了左子树和右子树的最大深度和l和r,那么该二叉树的最大深度为max(l,r)+1,同理,左子树和右子树的最大深度也可以以同样的逻辑计算。

9.3 代码

# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root is None:
            return 0
        else:
            left_height = self.maxDepth(root.left)
            right_height = self.maxDepth(root.right)
            return max(left_height, right_height) + 1

10 搜索插入位置

10.1 题目

        给定一个排序数组nums和一个目标值target,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

示例:

输入: nums = [1,3,5,6], target = 5
输出: 2

10.2 思路

        不断用二分法逼近查找第一个大于等于target的下标。

10.3 代码

def lower_bound(nums: List[int], target: int) -> int:
        left, right = 0, len(nums)-1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] < target:
                left = mid + 1
            else:
                right = mid - 1
        return left

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        return lower_bound(nums, target)

11 有效的括号

11.1 题目

        给一个只包括'(','[','{','}',']',')'的字符串s,判断字符串是否有效。有效字符串需要满足以下条件:①左括号必须用相同类型右括号闭合,②左括号以正确的顺序闭合,③每个右括号都有一个对应的左括号。

11.2 思路

        比较容易思考到栈,左括号依次入栈,右括号入栈后必须和此时在栈顶的左括号同时弹出栈顶,如果遍历结束栈为空,则返回True,否则返回False。

        一个比较容易忽视的点是,如果字符串s的元素数是奇数,则一定是False。

11.3 代码

class Solution:
    def isValid(self, s: str) -> bool:
        if len(s) % 2:
            return False
        mp = {')':'(', ']':'[', '}':'{'}
        st = []
        for c in s:
            if c not in mp:
                st.append(c)
            elif not st or st.pop() != ma[c]:
                return False
        return not st

12 买卖股票的最佳时机

12.1 题目

        给一个数组prices,第i个元素prices[i]表示一支股票第i天的价格,你只能在某一天买入这只股票,并在未来一个不同的日子卖出,设计一个算法计算出你能获取的最大利润。如果不能获取利润,返回0.

示例:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

12.2 思路

        从左到右枚举prices[i],首先找到第i天之前股票价格的最小值,作为买入价格minprice(只能是左侧的最小值);然后找到prices[i]-minprice的最大值,就是答案。

12.3 代码

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        ans = 0
        min_price = prices[0]
        for p in prices:
            ans = max(ans, p-min_price)
            min_price = min(min_price, p)
        return ans

13 爬楼梯

13.1 题目

        假设你在爬楼梯,需要爬n阶到楼顶。每次你可以爬1个或者2个台阶,你有多少种方法爬到楼顶。

示例:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

13.2 思路

        用dfs(i)表示从0爬到i有多少种方法,则dfs(i)=dfs(i-1)+dfs(i-2),其中dfs(0)=1,dfs(1)=1,则只需求出dfs(n)即可得到答案,所以可以采用递归的思路做。由于递归过程中会大量重复性计算,所以可以用一个@cache装饰器来保存过程中计算出来的值。

        同时,我们也可以从底往上计算,递推式和上面思路一样,仍然是f[i]=f[i-1]+f[i-2],f[0]=1,f[1]=1,求出f[n]即是答案。

13.3 代码

# 递归
class Solution:
    def climbStairs(self, n: int) -> int:
        @cache # 装饰器
        def dfs(i: int) -> int:
            if i <= 1:
                return 1
            return dfs(i-1) + dfs(i-2)
        return dfs(n)

# 递推
class Solution:
    def climbStairs(self, n: int) -> int:
        fo = f1 = 1
        for _ in range(2, n+1):
            new_f = f1 + f0
            f0 = f1
            f1 = new_f
        return f1
    

14 杨辉三角

14.1 题目

        给定一个非负整数numRows,生成杨辉三角的前numRows行。杨辉三角是指每个数是他左上方和右上方的数的和。

示例:

14.2 思路

        将杨辉三角的最左边的数对齐,这样每一排首尾数为1,其余每个数就等于其左上方的数和正上方的数之和。

14.3 代码

class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        c = [[1] * (i + 1) for i in range(numRows)]
        for i in range(2, numRows):
            for j in range(1, i):
                c[i][j] = c[i-1][j-1] + c[i-1][j]
        return c

15 只出现一次的数字

15.1 题目

        给你一个非空整数数组nums,除了某个元素只出现一次之外,其余元素都出现两次,请找出那个只出现一次的元素并返回。

示例:

输入:nums = [4,1,2,1,2]
输出:4

15.2 思路

        异或运算,a⊕a=0,(a⊕b)⊕c=a⊕(b⊕c),所以可以直接使用异或运算来找到那个只出现一次的元素。

15.3 代码

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        return reduce(xor, nums)

16 多数元素

16.1 题目

        给定一个大小为n的数组nums,返回其中的多数元素(即在数组中出现次数大于n/2的元素)。可以假设数组非空,且总是存在多数元素。

示例:

输入:nums = [2,2,1,1,1,2,2]
输出:2

16.2 思路

        既然多数元素是在数组中出现次数大于n/2的元素,如果我们对nums进行排序,那么下标为n/2的元素一定是多数元素。

16.3 代码

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        nums.sort()
        return nums[len(nums) // 2]

作者:Komorebi S

物联沃分享整理
物联沃-IOTWORD物联网 » leetcode hot 100——easy题(python)

发表回复