力扣中级算法(Python)

简介: 力扣中级算法(Python)

1 概述

概述

这是由 LeetCode 官方推出的的经典面试题目清单,我们将题目重新整理规划,从而为大家提供更好的练习体验和帮助大家找到理想的工作。 我们将题目分为以下三个部分:

初级算法 - 帮助入门

中级算法 - 巩固训练

高级算法 - 提升进阶

这一系列 LeetBook 将帮助您掌握算法及数据结构,并提高您的编程能力。


编程能力就像任何其他技能一样,也是一个可以通过 刻意练习 大大提高的。


大多数经典面试题目都有多种解决方案。 为了达到最佳的练习效果,我们强烈建议您至少将此清单里的题目练习两遍,如果可以的话,三遍会更好。


在第二遍练习时,你可能会发现一些新的技巧或新的方法。 到第三遍的时候,你会发现你的代码要比第一次提交时更加简洁。 如果你达到了这样的效果,那么恭喜你,你已经掌握了正确的练习方法!


记住:刻意练习并不意味着寻找答案并记住它,这种练习方法不是长久之计。 在没有参考答案情况下,越能自主解决问题,才越能提高自身能力。


作者:力扣 (LeetCode)

链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-medium/x6vk7r/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2  数组和字符串

2.1  三数之和

找出数组中和为0的三元组。

做法:转换成两数之和twoSum。固定第一个数a,问题就变成求和为-a的两数之和问题。然后可以用双指针解决。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        ans = []
        for first in range(0,len(nums)):
            #跳过重复的数
            if first > 0 and nums[first] == nums[first-1]:
                continue
            target = -nums[first] #变成求 和为-a的twoSum问题
            third = len(nums)-1
 
            for second in range(first+1,len(nums)):
                if second> first +1 and nums[second] == nums[second-1] :
                    continue
                while second<third and nums[second] + nums[third] > target:
                    third -= 1
                if second == third:
                    break
                if nums[second] + nums[third] == target:
                    ans.append([nums[first],nums[second],nums[third]])
 
        return ans


2.2 矩阵置零

容易想到用两个数组存储带0的行和列,然后将这些行和列置零。额外空间O(m+n)

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        row_0 = []
        col_0 = []
        for i in range(len(matrix)):
            for j in range(len(matrix[i])):
                if matrix[i][j] == 0:
                    row_0.append(i)
                    col_0.append(j)
        for i in row_0:
            for j in range(len(matrix[i])):
                matrix[i][j] = 0
        for j in col_0:
            for i in range(len(matrix)):
                matrix[i][j] = 0

如果要常数级空间O(1),用matrix的第一行和第一列来存储为0行和列。需要额外判断第一行,第一列是否存在0

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        row = False #第一行存在0
        col = False #第一列存在0
        for i in range(len(matrix)):
            for j in range(len(matrix[i])):
                if matrix[i][j] == 0:
                    if i == 0 :
                        row = True
                    if j == 0 :
                        col = True
 
                    matrix[i][0] = 0
                    matrix[0][j] = 0
                    
        
        for i in range(1,len(matrix)):
            for j in range(1,len(matrix[0])):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0
        if row:
            for j in range(0,len(matrix[0])):
                matrix[0][j] = 0
        if col:
            for i in range(0,len(matrix)):
                matrix[i][0] = 0
 

2.3 字母异位词分组

字典dict()

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        # 思路,遍历每个元素然后排序,若是异母同位词则排序后会相同,然后把相同的进行归为一类
        res = []
        dic = dict()
        for s in strs:
            l = [s]
            temp = list(s)
            temp.sort()
            dickey = ''.join(temp)
            if dickey in dic.keys():
                dic[dickey].append(s)
            else:
                dic[dickey] = l
        for i in dic.values():
            res.append(i)
        return res

2.4 无重复字符的最长子串

滑动窗口,每次窗口的左端 i 右移 一位;

关键点是:右端 r 保持,不需要回退。

例如s = "abcabcbb",第一个循环结束时 i = 0,r = 2,最长无重复子串是abc

第二个循环时,i=1,r=2,r不需要回退,因为abc包含了bc。

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        occ  = set()    
        maxLength,r = 0,0
        for i in range(len(s)):
            if i != 0:
                occ.remove(s[i-1])
            while r < len(s) and  s[r] not in occ:
                occ.add(s[r])
                r += 1
            if r-i > maxLength :
                maxLength = r - i
        return maxLength

2.5 最长回文子串

容易 想到动态规划实现。最长回文子串

用dp[i][j] 表示从i到j的子串是否是回文子串

递推式:

dp[i][j] =   s[i]== s[j] and dp[i+1][j-1]

终止条件:

i == j (length = 0), dp[i][j] = True

i+1 == j (length = 1), dp[i][j] =  s[i] == s[j]

注意初始化顺序,需要按长度length顺序初始化。而不是按起始位置i。因为dp[i][j]会依赖dp[i+1][j-1]的结果。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        dp = [[False for _ in range(n)] for _ in range(n)]
        ans = ""
        for length in range(n):
            for i in range(n-length):
                j = i + length
                if length == 0:
                    dp[i][j] = True
                elif length == 1:
                    dp[i][j] = s[i]==s[j]
                else:
                    dp[i][j] = s[i]== s[j] and dp[i+1][j-1]
                if dp[i][j] and length+1 > len(ans):
                    ans = s[i:i+length+1]
        return ans

2.6 递增的三元子序列

@Cany

我们只需要在从头到尾的遍历过程中,记录第一最小值small和第二最小值mid,然后当出现一个比第二最小值大的数,就能说明存在递增三元组的!

因为 mid的存在,永远说明前面有一个比自己小的数。所以不用担心small的下标到mid的后面。

例如2315,最后small = 1 ,mid = 3 large = 5 ,这三个下标不满足i<j<k,但mid前面一定有过比它小的数(2),所以是存在递增三元子序列的。

class Solution:
    def increasingTriplet(self, nums: List[int]) -> bool:
        
        small,mid = 2**31-1,2**31-1
        for num in nums:
            if num <= small:
                small = num
            elif num <= mid:
                mid = num
            else:
                return True
        return False

3 链表

3.1 两数相加

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        head,tail = None,None
        carry = 0
        while l1 != None or l2 != None :
            n1 = l1.val if l1 != None else 0
            n2 = l2.val if l2 != None else 0
            sum_t = n1 + n2 + carry
            if head == None:
                head = ListNode(sum_t % 10) 
                tail = head
            else:
                tail.next = ListNode(sum_t % 10)
                tail = tail.next
            carry = sum_t // 10
            if l1 != None:
                l1 = l1.next
            if l2 != None:
                l2 = l2.next
        
        if carry > 0 :
            tail.next = ListNode(carry)
        return head


3.2 奇偶链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def oddEvenList(self, head: ListNode) -> ListNode:
        isOdd = True
        OddHead,EvenHead = ListNode(),ListNode()
        OddCur,EvenCur = OddHead,EvenHead
        while head != None :
            if isOdd:
                OddCur.next = head
                OddCur = OddCur.next
            else:
                EvenCur.next = head
                EvenCur = EvenCur.next
            head = head.next
            isOdd = not isOdd
      
        OddCur.next = EvenHead.next
        EvenCur.next = None  #注意这里将EvenCur.next设置为None,不然就循环了
        return OddHead.next

3.3 相交链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
 
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        lenA = 0
        lenB = 0
        curA,curB = headA,headB
        while curA != None:
            lenA += 1
            curA = curA.next
        while curB != None:
            lenB += 1
            curB = curB.next
        diff = lenA - lenB
        if diff > 0:
            while diff > 0:
                headA = headA.next
                diff -= 1
        if diff <  0:
            while diff < 0:
                headB = headB.next
                diff += 1
        
        while headA != None and headB != None:
            if headA == headB:
                return headA
            headA = headA.next
            headB = headB.next
        
        return None

4 树和图

4.1 二叉树的中序遍历

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []
        self.inOrder(root, res)
        return res
    def inOrder(self, root,res):
        if root == None:
            return 
        self.inOrder(root.left,res)
        res.append(root.val)
        self.inOrder(root.right,res)

4.2 二叉树的锯齿形层次遍历

层次遍历+反转奇数层

1. # Def

4.3 从前序与中序遍历序列构造二叉树

递归。可以分成根,左,右三个子问题。

       root = TreeNode(preorder[0])

           #root_index = inorder.index(preorder[0])

           root.left = self.buildTree(preorder[1:root_index+1],inorder[:root_index])

           root.right = self.buildTree(preorder[root_index+1:],inorder[root_index+1:])

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if len(preorder)>0:
            #还有节点没有生成
            root = TreeNode(preorder[0])
            #找根节点位置
            root_index = inorder.index(preorder[0])
            #根据特性递归生成左右二叉树
            root.left = self.buildTree(preorder[1:root_index+1],inorder[:root_index])
            root.right = self.buildTree(preorder[root_index+1:],inorder[root_index+1:])
        else:
            root=None
        return root

4.4 填充每个节点的下一个右侧节点指针

层序遍历,,每层的最右边的没有next节点

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""
 
class Solution:
    def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
        if root == None:
            return root
        #层序遍历
        queue = [root]
        while queue:
            length = len(queue)
            pre = queue.pop(0)
            if pre.left:
              queue.append(pre.left)
              queue.append(pre.right)
 
            for i in range(length-1):
                t = queue.pop(0)
                if t.left:
                  queue.append(t.left)
                  queue.append(t.right)
                pre.next = t
                pre = t
        return root

4.5 二叉搜索树中第K小的元素

二叉搜索数满足 左<根<右,所以中序遍历得到的就是升序的数组。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.count = 0
        self.res = 0
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        self.count = k
        #inorder
        self.inorder(root)
        return self.res
        
        
    def inorder(self, root):
        if root == None:
            return
        self.inorder(root.left)
        self.count -=1
        if self.count == 0:
            self.res = root.val
        
        self.inorder(root.right)

4.6 岛屿数量

深度优先。因为连着的陆地只算一个岛屿,所以发现一个陆地后,岛屿数量+1,并将连着的陆地('1')变为水('0')

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    count +=1
                    self.dfs(i,j,grid)
        return count
        
    def dfs(self, i, j, grid):
        if i>=0 and i< len(grid) and j>=0 and j<len(grid[0]) and grid[i][j] == '1':
            grid[i][j] = '0'
            self.dfs(i+1,j,grid)
            self.dfs(i-1,j,grid)
            self.dfs(i,j-1,grid)
            self.dfs(i,j+1,grid)

5 回溯算法

回溯框架

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return
 
    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

5.1 电话号码的字母组合

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        phoneMap = {
            "2": "abc",
            "3": "def",
            "4": "ghi",
            "5": "jkl",
            "6": "mno",
            "7": "pqrs",
            "8": "tuv",
            "9": "wxyz",
        }
        res = []
        if len(digits) == 0 :
            return res
        self.backtrack(res, phoneMap, digits, 0,  [])
        return res
    
    #深度优先
    def backtrack(self, res, phoneMap, digits,index, st):
        if index == len(digits):
            res.append("".join(st))
        else:
            digit = digits[index]
            letters = phoneMap.get(digit)
            for letter in letters:
                st.append(letter)
                self.backtrack(res, phoneMap, digits, index+1, st)
                st.pop(index)

5.2 括号生成

有限制条件的回溯,因为数据量小,也可以先无限制条件生成括号,在判断是否合法。

class Solution:
    
    def generateParenthesis(self, n: int) -> List[str]:
        res = []
        self.backtrack(n,0,0,[],res)
        return res
    
    def backtrack(self,n,left,right,tmp,res):
        if right == n:
            res.append(''.join(tmp))
            return
        if left< n:
            tmp.append('(')
            self.backtrack(n,left+1,right,tmp,res)
            tmp.pop()
        if right<left:
            tmp.append(')') 
            self.backtrack(n,left,right+1,tmp,res)
            tmp.pop()

5.3 全排列

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        res = []
        self.backtrack(nums,[],res,len(nums))
        return res
 
    def backtrack(self,choices,tmp, res,n):
        if len(tmp) == n:
            res.append(tmp.copy())
            return
 
        for i in range(len(choices)):
            tmp.append(choices[i])
            choices.pop(i)  #
            self.backtrack(choices,tmp,res,n)
            choices.insert(i,tmp.pop())

5.4 子集

除了回溯也可以用  位运算&做

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []
        self.backtrack(nums,0,[],res)
        return res
 
    def backtrack(self,nums,start,tmp, res):
        res.append(tmp.copy())
        for i in range(start,len(nums)):
            tmp.append(nums[i])
            self.backtrack(nums,i+1,tmp,res)
            tmp.pop()

5.5 单词搜索

对每个棋子使用dfs。

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        for i in range(len(board)):
            for j in range(len(board[0])):
                if self.dfs(board,word,i,j,0):
                    return True
        return False
 
    def dfs(self, board, word, i,j,index):
        if i >= len(board) or i < 0 or j >= len(board[0]) or j < 0 or board[i][j] != word[index]:
            return False
        if index == len(word)-1:
            return True
        
        tmp = board[i][j]
        board[i][j] = '.'
        res = self.dfs(board,word,i+1,j,index+1) or self.dfs(board,word,i-1,j,index+1) or\
              self.dfs(board,word,i,j+1,index+1) or self.dfs(board,word,i,j-1,index+1)
        board[i][j] = tmp
        return res

6 排序和搜索

6.1  颜色分类

由于只有3种元素,可以直接统计频率,然后重写nums。

class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        a = [0,0,0]
        for i in nums:
            a[i] += 1
        index = 0
        for i in range(len(a)):
            for j in range(a[i]):
                nums[index] = i
                index +=1

6.2  前k个高频元素

使用字典存频率,然后排序(sort很简单,也可以最小堆heapq)。

 
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        mmap = dict()
        for num in nums:
            mmap[num] =  mmap[num]+1 if num in mmap else 1
        sort = sorted(zip(mmap.values(),mmap.keys()))
        sort.reverse()
        res = []
        for i in range(k):
            res.append(sort[i][1])
        return res

6.3 数组中的第K个最大元素

最大堆/直接排序

import heapq
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        #res = heapq.nlargest(k,nums)
        #return res[-1]
        return sorted(nums)[-k]

6.4 寻找峰值

虽然不是有序数组,但问题的形式可以用二分法。

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        length = len(nums)
        if  length == 1:
            return 0
        if  nums[0]>nums[1]:
            return 0
        if  nums[length-1]>nums[length-2]:
            return length-1 
        #二分查找
      
        left = 0
        right = length-1
        mid = (left+right)//2
        while left<right:
            mid = (left+right)//2
 
            if nums[mid]>nums[mid-1] and nums[mid]>nums[mid+1]:
                return mid
            elif nums[mid]<nums[mid-1]:
                right = mid
            elif nums[mid]<nums[mid+1]:
                left = mid
        return mid

6.5 在排序数组中查找元素的第一个和最后一个位置

遍历

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        length = len(nums)
        if length == 0:
            return [-1,-1]
        first = -1
        for i in range(length):
            if nums[i] == target:
                first = i
                break
        last = -1 
        for i in range(length-1,first-1,-1):
            if nums[i] == target:
                last = i  
                break
        return first,last

二分

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        length = len(nums)
        if length == 0:
            return [-1,-1]
        # first 
        first = -1 
        left = 0
        right = length-1
        while left <= right:
            mid = (left+right)//2
            if nums[mid] == target:
                first = mid
                right = mid-1
            elif nums[mid] > target :
                right = mid-1
            elif nums[mid]< target:
                left = mid+1
        #last 
        last = -1 
        left = first
        right = length-1
        mid = (left+right)//2
        while left <= right:
            mid = (left+right)//2
            if nums[mid] == target:
                left = mid+1
                last = mid
            elif nums[mid]< target:
                left = mid+1
            elif nums[mid] > target :
                right = mid-1
        return first,last

二分,但是简化了一下

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        length = len(nums)
        if length == 0 :
            return [-1,-1]
        first = -1  
        left,right = 0,length-1
        while left <= right:
            mid = (left+right)//2
            if nums[mid] >= target:
                right = mid-1
            elif nums[mid]< target:
                left = mid+1
        first = left
        if first not in range(length) or nums[first]!= target:
            return[-1,-1]
        #last 
        last = -1 
        left, right = first, length-1
        while left <= right:
            mid = (left+right)//2
            if nums[mid] <= target:
                left = mid+1
            elif nums[mid] > target :
                right = mid-1
        last = right
        return first,last

6.6 合并区间

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        length = len(intervals)
        if length <= 1:
            return intervals
        intervals.sort()
        tmp = intervals[0]
 
        res = []
        for num in intervals:
            if num[0] <= tmp[1] :
                tmp =[min(tmp[0],num[0]), max(tmp[1],num[1])]
            else:
                res.append(tmp)
                tmp = num
        print("res",res)
        if len(res)==0 or res[-1][1] < intervals[-1][0]:
            res.append(tmp) 
        return res

6.7  搜索旋转排序数组

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # step1 找旋转点
        res = -1
        length = len(nums)
        if length == 0:
            return -1
        if length == 1:
            return -1 if nums[0] != target else 0
        left, right = 0, length - 1
        zz = length - 1
        mid = (left + right) // 2
        while mid != left:
            mid = (left + right) // 2
            if nums[mid] > nums[left]:
                left = mid
            else :
                right = mid
        zz = right
        print("zz", zz)
        # step2 二分查找
        if target >= nums[0]:
            left, right = 0, zz - 1
        else:
            left, right = zz, length - 1
 
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] == target:
                res = mid
                break
            elif nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1
        return res

6.8 搜索二维矩阵 II

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        row = len(matrix)
        col = len(matrix[0])
        low_row = 0
        high_row = row-1
        while low_row < row and matrix[low_row][-1] < target  :
            low_row += 1
        while  high_row > 0 and matrix[high_row][0] > target :
            high_row -= 1
        for i in range(low_row, high_row+1):
            if self.b_search(matrix[i],target):
                return True
        return False
    
    def b_search(self, nums, target):
        left = 0
        right = len(nums)-1
        while left <= right :
            mid = (left+right)//2
            if nums[mid] == target:
                return True
            elif nums[mid] < target:
                left = mid +1
            elif nums[mid] > target:
                right = mid-1
        return False

7 动态规划

7.1 跳跃游戏

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        length = len(nums)
        if length == 1:
            return True
        #dp[i]:i位置能走的最远距离
        dp = [0 for _ in range(length )] 
        for i in range(len(nums)):
            dp[i] = max(dp[i-1]-1,nums[i])
            if i+dp[i] >= length-1:
                return True
            if dp[i] == 0:
                return False

7.2 不同路径

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        dp = [[1 for _ in range(n)] for _ in range(m)] 
        for row  in range(1,m):
            for col in range(1,n):
                dp[row][col] = dp[row-1][col] + dp[row][col-1]
        
        return dp[m-1][n-1]

7.3 零钱兑换

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [float('inf')] * (amount + 1)
        dp[0] = 0
        
        for coin in coins:
            for x in range(coin, amount + 1):
                dp[x] = min(dp[x], dp[x - coin] + 1)
        return dp[amount] if dp[amount] != float('inf') else -1

7.4  最长上升子序列

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        length = len(nums)
        dp = [1 for i in range(len(nums))]
        for i in range(length):
            for j in range(i):
                if nums[i] > nums[j]:
                    dp[i] = max(dp[j]+1, dp[i])
        return max(dp)

8 设计问题

8.1 二叉树的序列化与反序列化

前序遍历

class Codec:
 
    def serialize(self, root):
 
        """Encodes a tree to a single string.
        :type root: TreeNode
        :rtype: str
        """
        res = []
        def preorder(root):
            if not root:
                res.append('#')
                return
            res.append(str(root.val))
            preorder(root.left)
            preorder(root.right)
 
        preorder(root)
        return ','.join(res)
 
        return res
 
    def deserialize(self, data):
        """Decodes your encoded data to tree.
        :type data: str
        :rtype: TreeNode
        """
        arr = data.split(',')
        arr.reverse()
        def preorder(arr):
            if not arr:
                return
            if arr[-1] == '#':
                arr.pop()
                return
            root  = TreeNode(int(arr.pop()))
            root.left = preorder(arr)
            root.right = preorder(arr)
            return  root
        return  preorder(arr)

8.2 常数时间插入、删除和获取随机元素

使用字典记录元素

import random
 
 
class RandomizedSet:
 
    def __init__(self):
        self.arr = []
        self.length = 0
        self.mdict = {}
 
 
    def insert(self, val: int) -> bool:
        if val not in self.mdict:
            self.arr.append(val)
            self.mdict[val] = self.length
            self.length += 1
            return True
        else:
            return False
 
 
    def remove(self, val: int) -> bool:
        if val in self.mdict:
            index = self.mdict[val]
            del self.mdict[val]
            self.arr[index] = self.arr[-1]
            self.mdict[self.arr[-1]] = index
            self.arr.pop(-1)
            self.length -= 1
            return True
        else:
            return False
 
 
    def getRandom(self) -> int:
        return  random.choice(self.arr)
 
 
 
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()

9 数学

9.1 快乐数

class Solution:
    def isHappy(self, n: int) -> bool:
        def getn2(n):
            sum_n2 = 0
            while n:
                sum_n2 +=(n %10)**2
                n //=10
            return sum_n2
        d  = {}
        while n != 1 :
            if n in d:
                return False
            else:
                d[n] = True
                n = getn2(n)
        return True

9.2 阶乘后的零

阶乘中结果中的0是 2*5产生的,所以问题转化成求有多少个5。

class Solution:
    def trailingZeroes(self, n: int) -> int:
        res = 0
        while n>= 5:
            n //=5
            res += n
        return res

9.3 Excel表列序号

class Solution:
    def titleToNumber(self, columnTitle: str) -> int:
        res = 0
        for col in columnTitle:
            res *= 26
            res += ord(col) - ord('A')+1 #ord获取字符ascii值
            print(col)
        return res

9.4 Pow(x, n)

class Solution:
    def myPow(self, x: float, n: int) -> float:
        return x**n

9.5 x 的平方根

二分查找

class Solution:
    def mySqrt(self, x: int) -> int:
        left = 0
        right = x //2 if x >= 4 else x
        mid = (left+right)//2
        while left <= right:
            if  mid*mid <= x and (mid+1)*(mid+1) >x:
                return mid
            elif mid*mid > x:
                right = mid-1
            elif (mid+1)*(mid+1) <= x:
                left = mid+1
            mid = (left+right)//2
 
        return mid

9.6 两数相除

class Solution:
    def divide(self, dividend: int, divisor: int) -> int:
        if dividend == 0:
            return 0
        if dividend == -2**31 and divisor == -1: #-inf
            return 2**31-1 
        negative = (dividend ^ divisor) < 0 #符号位(最高位)不同,异或结果<0
        t = abs(dividend)
        d = abs(divisor)
        result = 0
        #转换成减法,利用移位的高效率
        for i in range(31,-1,-1):
            if (t>>i) >= d:
                result += 1<<i
                t -= d<<i
        return result if not negative else - result

9.7  分数到小数

class Solution:
    def fractionToDecimal(self, numerator: int, denominator: int) -> str:
        if numerator % denominator == 0:
            return str(numerator//denominator)
        s= []
        if numerator^denominator < 0:
            s.append('-')
        
        #整数
        numerator = abs(numerator)
        denominator = abs(denominator)
        intPart = numerator//denominator
        s.append(str(intPart))
        s.append('.')
 
        #小数
        indexMap = {}
        remainder = numerator % denominator
        while remainder and remainder not in indexMap:
            indexMap[remainder] = len(s)
            remainder *= 10
            s.append(str(remainder//denominator))
            remainder %= denominator
        if remainder:
            insertIndex = indexMap[remainder]
            s.insert(insertIndex,'(')
            s.append(')')
        
        return ''.join(s)

10 其它

10.1 两整数之和

class Solution:
    def getSum(self, a: int, b: int) -> int:
        #return sum([a,b])
        #位运算 a^b 实现无进位加法,在用a&b,并<< 获得进位
        if not b:
            return a
        return add(a^b,(a&b)<<1)

10.2 逆波兰表达式求值

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        res = 0
        for i in tokens:
            if i == '+' :
                a = stack.pop()
                b = stack.pop()
                stack.append(b+a)
            elif i == '-' :
                a = stack.pop()
                b = stack.pop()
                stack.append(b-a)
            elif i == '*' :
                a = stack.pop()
                b = stack.pop()
                stack.append(b*a)
            elif i == '/':
                a = stack.pop()
                b = stack.pop()
                stack.append(int(b/a))
            else :
                stack.append(int(i))
        return int(stack[-1])

10.3  多数元素

collection.Counter()

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        length = len(nums)
        freq = collections.Counter(nums)
    
        for k,v in freq.items():
            if v > length//2:
                return k

10.4  任务调度器

分析见官方题解。

class Solution:
    def leastInterval(self, tasks: List[str], n: int) -> int:
        freq = collections.Counter(tasks)
 
        maxExc = max(freq.values())
 
        maxCount = sum(1 for v in freq.values() if v == maxExc)
 
        return max((n+1)*(maxExc-1)+maxCount, len(tasks))
相关文章
|
15小时前
|
机器学习/深度学习 人工智能 算法
【球类识别系统】图像识别Python+卷积神经网络算法+人工智能+深度学习+TensorFlow
球类识别系统,本系统使用Python作为主要编程语言,基于TensorFlow搭建ResNet50卷积神经网络算法模型,通过收集 '美式足球', '棒球', '篮球', '台球', '保龄球', '板球', '足球', '高尔夫球', '曲棍球', '冰球', '橄榄球', '羽毛球', '乒乓球', '网球', '排球'等15种常见的球类图像作为数据集,然后进行训练,最终得到一个识别精度较高的模型文件。再使用Django开发Web网页端可视化界面平台,实现用户上传一张球类图片识别其名称。
15 7
【球类识别系统】图像识别Python+卷积神经网络算法+人工智能+深度学习+TensorFlow
|
2天前
|
存储 算法 Python
python常用算法(5)——树,二叉树与AVL树(一)
python常用算法(5)——树,二叉树与AVL树
|
2天前
|
存储 算法 Shell
python常用算法(5)——树,二叉树与AVL树(三)
python常用算法(5)——树,二叉树与AVL树
|
2天前
|
算法 Python
python常用算法(5)——树,二叉树与AVL树(二)
python常用算法(5)——树,二叉树与AVL树
|
1天前
|
人工智能 算法 物联网
求解三维装箱问题的启发式深度优先搜索算法(python)
求解三维装箱问题的启发式深度优先搜索算法(python)
6 0
|
1天前
|
算法 Python
模拟退火算法求解TSP问题(python)
模拟退火算法求解TSP问题(python)
5 0
|
1天前
|
算法 C语言 Python
简单遗传算法优化简单一元函数(python)
简单遗传算法优化简单一元函数(python)
4 0
|
1天前
|
算法 Python
利用深度优先搜索算法解决老鼠吃奶酪问题(python)
利用深度优先搜索算法解决老鼠吃奶酪问题(python)
2 0
|
7天前
|
测试技术 虚拟化 云计算
GitHub高赞!速通Python编程基础手册,被玩出花了!
随着云时代的来临,Python 语言越来越被程序开发人员喜欢和使用,因为其不仅简单易学,而且还有丰富的第三方程序库和相应完善的管理工具。 从命令行脚本程序到 GUI程序,从图形技术到科学计算,从软件开发到自动化测试,从云计算到虚拟化,所有这些领域都有 Python 的身影。 今天给小伙伴们分享的这份手册采用以任务为导向的编写模式,全面地介绍了 Python 编程基础及其相关知识的应用,讲解了如何利用 Python 的知识解决部分实际问题。
GitHub高赞!速通Python编程基础手册,被玩出花了!
|
4天前
|
开发者 Python
【干货】Python编程惯例
【干货】Python编程惯例
10 1