手撕代码。。

112 阅读4分钟

二叉树

三种遍历非递归
# 先序打印二叉树(非递归)
def preOrderTravese(node):
    stack = [node]
    while len(stack) > 0:
        print(node.val)
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
        node = stack.pop()

# 中序打印二叉树(非递归)
def inOrderTraverse(node):
    stack = []
    pos = node
    while pos or len(stack) > 0:
        if pos:
            stack.append(pos)
            pos = pos.left
        else:
            pos = stack.pop()
            print(pos.val)
            pos = pos.right
# 后序打印二叉树(非递归)实现根右左 然后再反向
#  todo
leetcode199-二叉树的右视图
class Solution:
    def rightSideView(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        res = []
        queue = [root]
        while queue:
            idx = len(queue)-1
            for i in range(len(queue)):
                cur  = queue.pop(0)
                if i==idx:
                    res.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
        return res
leetcode124-二叉树最大路径和

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)
        return self.maxSum

leetcode534-二叉树的直径
class Solution:
    def diameterOfBinaryTree(self, root: TreeNode) -> int:
        if not root:
            return 0
        leftdepth = self.depth(root.left)
        rightdepth = self.depth(root.right)
        return max(leftdepth+rightdepth,self.diameterOfBinaryTree(root.left),self.diameterOfBinaryTree(root.right))

    def depth(self,node):
        if not node:
            return 0
        return 1+max(self.depth(node.left),self.depth(node.right))
class Solution:
    
    def __init__(self):
        self.max = 0
    
    def diameterOfBinaryTree(self, root: TreeNode) -> int:
        self.depth(root)     
        return self.max
        
    def depth(self, root):
        if not root:
            return 0
        l = self.depth(root.left)
        r = self.depth(root.right)
        '''每个结点都要去判断左子树+右子树的高度是否大于self.max,更新最大值'''
        self.max = max(self.max, l+r)       
        # 返回的是高度
        return max(l, r) + 1
leetcode105-前序后序构造二叉树
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if len(preorder)==0:
            return None
        elif len(preorder)==1:
            return TreeNode(preorder[0])
        else:
            root = TreeNode(preorder[0])
            root.left = self.buildTree(preorder[1:inorder.index(preorder[0])+1],inorder[:inorder.index(preorder[0])])
           		          					    root.right=self.buildTree(preorder[inorder.index(preorder[0])+1:],inorder[inorder.index(preorder[0])+1:])
        return root
leetcode110-平衡二叉树

时间复杂度O(n^2) 空间复杂度O(n)

class Solution:   
    def isBalanced(self, root: TreeNode) -> bool:
        def height(node):
            if not node:
                return 0
            return 1+max(height(node.left),height(node.right))
        
        if not root:
            return True
        if abs(height(root.left)-height(root.right))>1:
            return False
        return self.isBalanced(root.left) and self.isBalanced(root.right)

时间复杂度O(n) 空间复杂度O(n)

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        return self.recur(root) != -1

    def recur(self, root):
        if not root: return 0
        left = self.recur(root.left)
        if left == -1: return -1
        right = self.recur(root.right)
        if right == -1: return -1
        return max(left, right) + 1 if abs(left - right) < 2 else -1

链表

leetcode25-K 个一组翻转链表
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        dummy = ListNode(0)
        p = dummy
        while True:
            count = k 
            stack = []
            tmp = head
            while count and tmp:
                stack.append(tmp)
                tmp = tmp.next
                count -= 1
            # 注意,目前tmp所在k+1位置
            # 说明剩下的链表不够k个,跳出循环
            if count : 
                p.next = head
                break
            # 翻转操作
            while stack:
                p.next = stack.pop()
                p = p.next
            #与剩下链表连接起来 
            p.next = tmp
            head = tmp
        
        return dummy.next
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        cur = head
        count = 0
        while cur and count!= k:
            cur = cur.next
            count += 1
        if count == k:
            cur = self.reverseKGroup(cur, k)
            while count:
                tmp = head.next
                head.next = cur
                cur = head
                head = tmp
                count -= 1
            head = cur   
        return head
leetcode146-LRU缓存机制
class DLinkNode:
    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.d1 = dict()
        self.capacity = capacity
        self.head = DLinkNode()
        self.tail = DLinkNode()
        self.head.next = self.tail
        self.tail.prev = self.head
        self.size = 0

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

    def put(self, key: int, value: int) -> None:
        if key in self.d1:
            node = self.d1[key]
            node.value = value
            self.move2Head(node)
        else:
            node = DLinkNode(key,value)
            self.d1[key] = node
            self.add2Head(node)
            self.size += 1
            if self.size>self.capacity:
                removed = self.removeTail()
                self.d1.pop(removed.key)
                self.size -= 1
    
    def add2Head(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 move2Head(self,node):
        self.removeNode(node)
        self.add2Head(node)

    def removeTail(self):
        node = self.tail.prev
        self.removeNode(node)
        return node
leetcode234-回文链表

空间复杂度O(n)数组保存再判断

空间复杂度O(1)

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        pre, slow, fast = None, head, head
        while fast and fast.next:
            fast = fast.next.next
            temp = pre
            pre, slow = slow, slow.next
            pre.next = temp
        if fast:
            slow = slow.next
        while pre and pre.val == slow.val:
            slow = slow.next
            pre = pre.next
        return not pre

leetcode2-两数相加(链表)
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        n3 = 0
    
        n1 = self.Link2Int(l1)
        n2 = self.Link2Int(l2)

        n3 = n1 + n2
        len1,cn3 = 1,n3
        while cn3>=10:
            cn3 = cn3//10
            len1 += 1
        cur = head = ListNode(0)
        for _ in range(len1):
            cur.next = ListNode(n3%10)
            cur = cur.next
            n3 = n3//10
        return head.next
    
    def Link2Int(self,l):
        num = []
        n = 0
        while l:
            num.append(l.val)
            l = l.next
        for i in range(len(num)):
            n += num[i]*10**i
        return n

字符串

剑指 Offer 48. 最长不含重复字符的子字符串
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if len(s)<2:
            return len(s)
        l,r,res = 0,0,0
        slist = set()
        while r<len(s):
            if s[r] not in slist:
                slist.add(s[r])
                r+=1
                res = max(res,len(slist))
            else:
                slist.remove(s[l])
                l+=1
        return res

动态规划

操作数组

leetcode15-三数之和
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        n=len(nums)
        res=[]
        if(not nums or n<3):
            return res
        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=L+1
                    while(L<R and nums[R]==nums[R-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1
                else:
                    L=L+1
        return res
leetcode33-搜索旋转排序数组

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

leetcode88-合并两个有序数组
class Solution(object):
    def merge(self, nums1, m, nums2, n):
        # two get pointers for nums1 and nums2
        p1 = m - 1
        p2 = n - 1
        # set pointer for nums1
        p = m + n - 1   
        # while there are still elements to compare
        while p1 >= 0 and p2 >= 0:
            if nums1[p1] < nums2[p2]:
                nums1[p] = nums2[p2]
                p2 -= 1
            else:
                nums1[p] =  nums1[p1]
                p1 -= 1
            p -= 1

排序算法

快排
def quicksort(nums):
    if len(nums)<2:
        return
    quicksorthelp(nums,0,len(nums)-1)
    return nums
def quicksorthelp(nums,l,r):
    if l<r:
        randomnum = random.randint(l,r)
        swap(nums,randomnum,r)
    if l<r:
        p = partition(nums,l,r)
        quicksorthelp(nums,l,p[0]-1)
        quicksorthelp(nums,p[1]+1,r)
def partition(nums,l,r):
    small = l-1
    big = r
    while l<big:
        if nums[l]<nums[r]:
            small += 1
            swap(nums,small,l)
            l += 1
        elif nums[l]>nums[r]:
            big -=1
            swap(nums,big,l)
        else:
            l += 1
    swap(nums,big,r)
    return [small+1,big]
堆排
    def heapify3(self,nums,i,l):
        left,right = 2*i+1,2*i+2
        s_idx = i
        if left<l and nums[left]<nums[s_idx]:
            s_idx = left
        if right<l and nums[right]<nums[s_idx]:
            s_idx = right
        if s_idx != i:
            nums[i],nums[s_idx] = nums[s_idx],nums[i]
            self.heapify3(nums,s_idx,l)
    def heap_sort3(self,nums):
        l = len(nums)
        for i in range(l//2-1,-1,-1):
            self.heapify3(nums,i,l)  
        for j in range(l-1,0,-1):
            nums[j],nums[0] = nums[0],nums[j]
            self.heapify3(nums,0,j)
        return nums
归并排序
def mergesort(nums):
    #1.拆开
    mid = len(nums)//2
    if mid<1:
        return nums
    #2.归并 Sort_Merge
    left = mergesort(nums[0:mid])
    right = mergesort(nums[mid:])
    res = []
    indexl,indexr=0,0
    while indexl <len(left) and indexr<len(right):
        if left[indexl]>right[indexr]:
            res.append(right[indexr])
            indexr += 1
        else:
            res.append(left[indexl])
            indexl += 1
    if indexl == len(left):
        res += right[indexr:]
    else:
        res += left[indexl:]
    return res

DFS

BFS

回溯法

位运算