高频算法题2

左右边界

int left_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    // 搜索区间为 [left, right]
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            // 搜索区间变为 [mid+1, right]
            left = mid + 1;
        } else if (nums[mid] > target) {
            // 搜索区间变为 [left, mid-1]
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 收缩右侧边界
            right = mid - 1;
        }
    }
    // 检查出界情况
    if (left >= nums.length || nums[left] != target) {
        return -1;
    }
    return left;
}

int right_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 这里改成收缩左侧边界即可
            left = mid + 1;
        }
    }
    // 这里改为检查 right 越界的情况,见下图
    if (right < 0 || nums[right] != target) {
        return -1;
    }
    return right;
}

比目标值大的最右边界

def get_target(nums,target):
    if len(nums) == 0 : return -1
    if target < nums[0]:
        return 0
    if target > nums[-1]:
        return -1
    left = 0
    right = len(nums)

    while left < right:
        mid = left + (right-left) // 2
        if nums[mid] == target:
            left = mid + 1
        elif nums[mid] < target:
            left = mid + 1
        elif nums[mid] > target:
            right = mid
    res = left-1 if left != 0 and nums[left-1] == target else left
    return res

滑动窗口最大值

def maxSlidingWindow(nums,k):
    if not nums or k == 0:return []
    deque = collections.deque()
    for i in range(k):
        while deque and deque[-1] < nums[i]:
            deque.pop()
        deque.append(nums[i])
    res = [deque[0]]
    for i in range(k,len(nums)):
        if deque[0] == nums[i-k]:
            deque.popleft()
        while deque and deque[-1] < nums[i]:
            deque.pop()
        deque.append(nums[i])
        res.append(deque[0])
    return res

排序数组查找第一个位置和最后一个位置

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        leftindex = self.binary(nums,target,True)
        rightindex = self.binary(nums,target,False)-1
        if leftindex <= rightindex and rightindex < len(nums) and nums[leftindex] == target and nums[rightindex] == target:
            return [leftindex,rightindex]
        return [-1,-1]

    def binary(self,nums,target,lower):
        left = 0
        right = len(nums)-1
        ans = len(nums)

        while left <= right:
            mid =(left + right) // 2
            if (nums[mid] >  target) or (lower and nums[mid] >= target):
                right = mid - 1
                ans = mid 
            else:
                left = mid + 1
        return ans

快速排序

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def quick_sort(start,end):
            if start >= end : return 
            idx = random.randint(start,end)
            nums[start],nums[idx] = nums[idx],nums[start]
            privor = nums[start]
            l,r = start,end 
            while l < r:
                while l < r and nums[r] >= privor:
                    r -= 1
                while l < r and nums[l] <= privor:
                    l += 1 
                nums[l],nums[r] = nums[r],nums[l]
            nums[start],nums[l] = nums[l],nums[start]
            quick_sort(start,l-1)
            quick_sort(l+1,end)

        quick_sort(0,len(nums)-1)
        return nums

无重复最长子串

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        setc = set()
        n = len(s)
        rk = -1
        ans = 0

        for i in range(n):
            if i != 0:
                setc.remove(s[i-1])
            while rk + 1 < n and s[rk + 1] not in setc:
                setc.add(s[rk+1])
                rk += 1

            ans = max(ans,rk-i+1)
        return ans 

迭代实现中序遍历

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        # res = []
        # def dfs(root):
        #     if not root:
        #         return 
        #     dfs(root.left)
        #     res.append(root.val)
        #     dfs(root.right)
        
        # dfs(root)
        # return res 
        stack,rst = [root],[]
        while stack:
            i = stack.pop()
            if isinstance(i,TreeNode):
                stack.extend([i.right,i.val,i.left])
            elif isinstance(i,int):
                rst.append(i)
        return rst

矩阵最大路径和

合并2个有序数组

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        sorted = []
        p1,p2 = 0,0
        while p1 < m or p2 < n:
            if p1 == m:
                sorted.append(nums2[p2])
                p2 += 1
            elif p2 == n:
                sorted.append(nums1[p1])
                p1 += 1
            elif nums1[p1] < nums2[p2]:
                sorted.append(nums1[p1])
                p1 += 1
            else:
                sorted.append(nums2[p2])
                p2 += 1
        nums1[:] = sorted

合并2个有序链表

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

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        cur = dum = ListNode(0)
        while l1 and l2:
            if l1.val < l2.val:
                cur.next,l1 = l1,l1.next
            else:
                cur.next,l2 = l2,l2.next
            cur = cur.next
        cur.next = l1 if l1 else l2
        return dum.next

合并n个有序数组

合并n个有序链表

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        import heapq
        dummy = ListNode(0)
        p = dummy
        head = []
        for i in range(len(lists)):
            if lists[i] :
                heapq.heappush(head, (lists[i].val, i))
                lists[i] = lists[i].next
        while head:
            val, idx = heapq.heappop(head)
            p.next = ListNode(val)
            p = p.next
            if lists[idx]:
                heapq.heappush(head, (lists[idx].val, idx))
                lists[idx] = lists[idx].next
        return dummy.next

第k大数

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        def partition(nums,l,r):
            privot = nums[r]
            i = l-1
            for j in range(l,r):
                if nums[j]  >= privot:
                    i += 1
                    nums[i],nums[j] = nums[j],nums[i]
            nums[i+1],nums[r] = nums[r],nums[i+1]
            return i+1
        l = 0
        r = len(nums) -1
        while True:
            privot_index = partition(nums,l,r)
            if privot_index == k-1:return nums[k-1]
            elif privot_index < k-1:
                l = privot_index + 1
            else:
                r = privot_index -1

有序矩阵中第 K 小的元素

class Solution:
    def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
        n = len(matrix)

        def check(mid):
            i,j = n-1,0
            num = 0
            while i >= 0 and j < n:
                if matrix[i][j] <= mid:
                    num += i + 1
                    j += 1
                else:
                    i -= 1
            return num >= k
        left,right = matrix[0][0],matrix[-1][-1]
        while left < right:
            mid = (left + right) // 2
            if check(mid):
                right = mid
            else:
                left = mid + 1
        return left

两数之和

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

三数之和

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        res = []
        if n < 3:
            return []
        nums.sort()
        for i in range(n):
            if nums[i] > 0: return res 
            if i > 0 and nums[i] == nums[i-1]:continue
            L = i+1
            R = n - 1

            while L < R:
                if nums[i] + nums[L] + nums[R] == 0:
                    res.append([nums[i],nums[L],nums[R]])
                    while L < R and nums[L] == nums[L+1]:
                        L += 1
                    while L < R and nums[R] == nums[R - 1]:
                        R -= 1
                    
                    L += 1
                    R -= 1
                elif nums[i] + nums[L] + nums[R] > 0:
                    R -= 1
                else:
                    L += 1
        return res

灯泡开关

数组中超过一半的数字

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        votes = 0
        for num in nums:
            if votes == 0:x = num 
            if x == num : votes += 1
            else : votes -= 1
        return x 

树的深度遍历

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root : return 0
        return max(self.maxDepth(root.left),self.maxDepth(root.right)) + 1

二叉树前序遍历

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        stack,rst = [root],[]
        while stack:
            i = stack.pop()
            if isinstance(i,TreeNode):
                stack.extend([i.right,i.left,i.val])
            elif isinstance(i,int):
                rst.append(i)
        return rst

链表m到n位置反转

class Solution(object):
    def reverseBetween(self, head, left, right):
        count = 1
        dummy = ListNode(0)
        dummy.next = head
        pre = dummy
        while pre.next and count < left:
            pre = pre.next
            count += 1
        cur = pre.next
        tail = cur
        while cur and count <= right:
            nxt = cur.next
            cur.next = pre.next
            pre.next = cur
            tail.next = nxt
            cur = nxt
            count += 1
        return dummy.next

最小栈

import math
class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stack = []
        self.min_stack = [math.inf]


    def push(self, x: int) -> None:
        self.stack.append(x)
        self.min_stack.append(min(x,self.min_stack[-1]))

    def pop(self) -> None:
        self.stack.pop()
        self.min_stack.pop()

    def top(self) -> int:
        return self.stack[-1]

    def getMin(self) -> int:
        return self.min_stack[-1]

盛水最多的容器

def maxArea(height):
    l,r = 0,len(higth)-1
    ans = 0
    while l < r:
        area = min(height[l],height[r]) * (r-l)
        ans = max(area,ans)
        if height[l] < height[r]:
            l += 1
        else:
            r -= 1
    return ans

有序数组中目标值出现的次数

接雨水

去除重复字母

class Solution:
    def removeDuplicateLetters(self, s) -> int:
        stack = []
        remain_counter = collections.Counter(s)

        for c in s:
            if c not in stack:
                while stack and c < stack[-1] and  remain_counter[stack[-1]] > 0:
                    stack.pop()
                stack.append(c)
            remain_counter[c] -= 1
        return ''.join(stack)

实现根号

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

先序遍历+中序遍历 生成后序遍历

先序遍历+中序遍历 构造二叉树

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        def myBuildTree(preorder_left,preorder_right,inorder_left,inorder_right):
            if preorder_left > preorder_right:
                return None
            preorder_root = preorder_left
            inorder_root = index[preorder[preorder_root]]

            root = TreeNode(preorder[preorder_root])
            size_left_subtree = inorder_root - inorder_left
            root.left = myBuildTree(preorder_left + 1,preorder_left + size_left_subtree,inorder_left, inorder_root - 1)
            root.right = myBuildTree(preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right)
            return root

        n = len(preorder)
        index = {element: i for i,element in enumerate(inorder)}
        return myBuildTree(0,n-1,0,n-1)

搜索旋转排序数组

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        lo,hi = 0,len(nums)-1
        while lo <= hi:
            mid = lo+(hi - lo) // 2
            if nums[mid] == target:
                return mid 
            
            elif nums[lo] <= nums[mid]:
                if nums[lo] <= target and target < nums[mid]:
                    hi = mid - 1
                else:
                    lo = mid + 1 
            else:
                if nums[mid] < target and target <= nums[hi]:
                    lo = mid + 1
                else:
                    hi = mid - 1

        return -1

最长公共子序列

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m,n = len(text1),len(text2)
        dp = [[0] * ( n+ 1) for _ in range(m + 1)]

        for i in range(1,m+1):
            for j in range(1,n+1):
                if text1[i-1] == text2[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                else:
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1])
        return dp[-1][-1]

旋转数组

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return list()
        
        rows, columns = len(matrix), len(matrix[0])
        order = list()
        left, right, top, bottom = 0, columns - 1, 0, rows - 1
        while left <= right and top <= bottom:
            for column in range(left, right + 1):
                order.append(matrix[top][column])
            for row in range(top + 1, bottom + 1):
                order.append(matrix[row][right])
            if left < right and top < bottom:
                for column in range(right - 1, left, -1):
                    order.append(matrix[bottom][column])
                for row in range(bottom, top, -1):
                    order.append(matrix[row][left])
            left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1
        return order

字符串的正则表达式

cache缓存

class DLinkedNode:
    def __init__(self,key=0,value=0):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None


class LRUCache:

    def __init__(self, capacity: int):
        self.cache = dict()
        self.head = DLinkedNode()
        self.tail = DLinkedNode()
        self.head.next = self.tail
        self.tail.prev = self.head
        self.capacity = capacity
        self.size = 0

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        node = self.cache[key]
        self.moveToHead(node)
        return node.value

    def put(self, key: int, value: int) -> None:
        if key not in self.cache:
            node = DLinkedNode(key,value)
            self.cache[key] = node
            self.addToHead(node)
            self.size += 1
            if self.size > self.capacity:
                removed = self.removeTail()
                self.cache.pop(removed.key)
                self.size -= 1
        else:
            node = self.cache[key]
            node.value = value
            self.moveToHead(node)
    def addToHead(self,node):
        node.prev = self.head
        node.next = self.head.next
        self.head.next.prev = node
        self.head.next = node
    def removeNode(self,node):
        node.prev.next = node.next
        node.next.prev = node.prev
    def moveToHead(self,node):
        self.removeNode(node)
        self.addToHead(node)
    def removeTail(self):
        node = self.tail.prev
        self.removeNode(node)
        return node

k个一组翻转链表

class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        def reverse(head):
            pre = None
            cur = head
            while cur:
                tmp = cur.next
                cur.next = pre
                pre = cur
                cur = tmp 
            return pre
        dum = ListNode(0)
        dum.next = head
        pre,end = dum,dum 
        while end.next :
            for i in range(k):
                if end:
                    end = end.next 
            if not end:break 
            start = pre.next 
            next1 = end.next 
            end.next = None
            pre.next = reverse(start)
            start.next = next1
            pre = start 
            end = pre

最长连续子序列

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        # dp = [0] * len(nums)
        # dp[0] = nums[0]
        # for i in range(1,len(nums)):
        #     if dp[i-1] > 0:
        #         dp[i] = dp[i-1] + nums[i]
        #     else:
        #         dp[i] = nums[i]
        # return max(dp)
        sum_v = nums[0]
        max_v = nums[0]
        for i in range(1,len(nums)):
            if sum_v > 0:
                sum_v += nums[i]
            else:
                sum_v = nums[i]
            max_v = max(max_v,sum_v)
        return max_v 

最长递增子序列

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

树左叶子到右叶子节点的最大路径和

class Solution:
    def __init__(self):
        self.maxSum = float("-inf")
        
    def maxPathSum(self, root: TreeNode) -> int:
        def maxGain(node):
            if not node:
                return 0

            # 递归计算左右子节点的最大贡献值
            # 只有在最大贡献值大于 0 时,才会选取对应子节点
            leftGain = max(maxGain(node.left), 0)
            rightGain = max(maxGain(node.right), 0)
            
            # 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
            priceNewpath = node.val + leftGain + rightGain
            
            # 更新答案
            self.maxSum = max(self.maxSum, priceNewpath)
        
            # 返回节点的最大贡献值
            return node.val + max(leftGain, rightGain)
   
        maxGain(root)

最长回文子串

class Solution:
    def aroundCenter(self,s,left,right):
        while left >= 0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
        return left + 1 , right - 1
    def longestPalindrome(self, s: str) -> str:
        start,end = 0,0
        for i in range(len(s)):
            left1,right1 = self.aroundCenter(s,i,i)
            left2,right2 = self.aroundCenter(s,i,i+1)

            if right1 - left1 > end - start:
                start,end = left1,right1 
            
            if right2 - left2 > end - start:
                start,end = left2,right2 
        
        return s[start:end+1]

最小高度二叉树

组合总和2

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        def dfs(begin,path,residue):
            if residue == 0:
                res.append(path[:])
                return
            for index in range(begin,size):
                if candidates[index] > residue:
                    break
                if index > begin and candidates[index - 1] == candidates[index]:
                    continue
                path.append(candidates[index])
                dfs(index+1,path,residue - candidates[index])
                path.pop()
        size = len(candidates)
        if size == 0:
            return []
        candidates.sort()
        res = []
        dfs(0,[],target)
        return res

岛屿数量

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        def dfs(grid,i,j):
            if not 0 <= i < len(grid) or not 0 <= j < len(grid[0]) or grid[i][j] == '0':return 
            grid[i][j] = '0'

            dfs(grid,i+1,j)
            dfs(grid,i-1,j)
            dfs(grid,i,j+1)
            dfs(grid,i,j-1)
        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    dfs(grid,i,j)
                    count +=1
        return count

编辑距离

# 编辑距离
def minDistance(self, word1: str, word2: str) -> int:
        n1 = len(word1)
        n2 = len(word2)
        dp = [[0] * (n2+1) for _ in range(n1 + 1)]

        for i in range(1,n1 + 1):
            dp[i][0] = dp[i-1][0] + 1
        for j in range(1,n2 + 1):
            dp[0][j] = dp[0][j-1]  + 1

        for i in range(1,n1 + 1):
            for j in range(1,n2 + 1):
                if word1[i-1] == word2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]) + 1
        return dp[-1][-1]

你可能感兴趣的:(高频算法题2)