算法工程师面试——算法代码准备

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明,违反必究。
本文链接:https://blog.youkuaiyun.com/junxing2018_wu/article/details/117440975

二叉树遍历

# -*- coding: utf-8 -*-

from typing import List


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


class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        # 根 左 右
        if root is None:
            return []
        result = [root.val]
        stack = [root.right, root.left]
        while len(stack) > 0:
            node = stack.pop()
            if node is not None:
                result.append(node.val)
                stack.extend([node.right, node.left])
        return result

    def postorderTraversal(self, root: TreeNode) -> List[int]:
        # 左 右 根
        # = [根 右 左][::-1]
        if root is None:
            return []
        result = [root.val]
        stack = [root.left, root.right]
        while len(stack) > 0:
            node = stack.pop()
            if node is not None:
                result.append(node.val)
                stack.extend([node.left, node.right])
        return result[::-1]

    def inorderTraversal(self, root: TreeNode) -> List[int]:
        # 左 根 右
        if root is None:
            return []
        node = root
        result = []
        stack = []
        while stack or node:
            while node:
                stack.append(node)
                node = node.left
            if stack:
                node = stack.pop()
                result.append(node.val)
                node = node.right
        return result

    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        def children(root: TreeNode):
            return [n for n in [root.left, root.right] if n is not None]

        if root is None:
            return []
        else:
            result = []
            node_list = [root]
            while len(node_list) > 0:
                result.append([n.val for n in node_list])
                tmp_stack = []
                for n in node_list:
                    tmp_stack += children(n)
                node_list = tmp_stack
            return result

if __name__ == "__main__":
    a = TreeNode("a")
    b = TreeNode("b")
    c = TreeNode("c")
    d = TreeNode("d")
    e = TreeNode("e")
    f = TreeNode("f")
    g = TreeNode("g")

    a.left = b
    a.right = c
    b.left = d
    b.right = e
    c.left = f
    c.right = g

    s = Solution()
    print(s.postorderTraversal(a))
    print(s.preorderTraversal(a))
    print(s.inorderTraversal(a))

数组排序

# -*- coding: utf-8 -*-

import copy, random
from typing import List


class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        # return self.bubblesort(nums)
        # return self.selectsort(nums)
        # return self.insertionsort(nums)
        # return self.shellsort(nums)
        # return self.quicksort(nums, 0, len(nums)-1)
        # return self.mergesort(nums)
        return self.heapsort(nums)

    def swapnum(self, nums: List[int], i: int, j: int) -> List[int]:
        nums[i], nums[j] = nums[j], nums[i]

    def bubblesort(self, nums: List[int]) -> List[int]:
        l = len(nums)
        for i in range(l):
            for j in range(1, l):
                if nums[j - 1] > nums[j]:
                    self.swapnum(nums, j - 1, j)
        return nums

    def selectsort(self, nums: List[int]) -> List[int]:
        l = len(nums)
        if l <= 1:
            return nums
        for i in range(l - 1):
            # index_min_num:i
            for j in range(i, l):
                if nums[j] < nums[i]:
                    self.swapnum(nums, i, j)
        return nums

    def insertionsort(self, nums: List[int]) -> List[int]:
        l = len(nums)
        for i in range(1, l):
            need_insert_num = nums[i]
            # 将nums[i]插入已排序序列nums[1..j-1]
            j = i - 1
            while j >= 0 and nums[j] > need_insert_num:
                nums[j + 1] = nums[j]
                j -= 1
            nums[j + 1] = need_insert_num
        return nums

    # 希尔排序
    def shellsort(self, nums: List[int]) -> List[int]:
        l = len(nums)
        gap = 1
        gapc = 3
        while gap < l / gapc:
            gap = gap * gapc + 1
        while gap > 0:
            # 下边就是一个插入排序
            for i in range(gap, l):
                temp = nums[i]
                j = i - gap
                while j >= 0 and nums[j] > temp:
                    nums[j + gap] = nums[j]
                    j -= gap
                nums[j + gap] = temp
            gap = gap // gapc
        return nums

    def mergesort(self, nums: List[int]) -> List[int]:
        def mergenums(left: list, right: list):
            result = []
            while left and right:
                if left[0] <= right[0]:
                    result.append(left.pop(0))
                else:
                    result.append(right.pop(0))
            result += left + right
            return result

        l = len(nums)
        if l < 2:
            return nums
        middle_index = l >> 1
        return mergenums(
            self.mergesort(nums[:middle_index]), self.mergesort(nums[middle_index:])
        )

    def quicksort(self, nums: List[int], left: int, right: int) -> List[int]:
        def partition(nums, left, right):
            index = left + 1
            for i in range(index, right + 1):
                if nums[i] < nums[left]:
                    self.swapnum(nums, i, index)
                    index += 1
            self.swapnum(nums, left, index - 1)
            return index - 1

        if left < right:
            partitionindex = partition(nums, left, right)
            self.quicksort(nums, left, partitionindex - 1)
            self.quicksort(nums, partitionindex + 1, right)
        return nums

    def heapsort(self, nums):
        """
        堆排序
        """

        def build_maxheap(nums):
            """
            创建大根堆
            """
            for i in range(len(nums) // 2, -1, -1):
                # 从最外层开始构建大根堆
                max_heapify(nums, i, len(nums))

        def max_heapify(nums, i, size):
            """
            最大化堆,i 为 堆头id
            """
            left = 2 * i + 1
            right = 2 * i + 2
            largest = i
            if left < size and nums[left] > nums[largest]:
                largest = left
            if right < size and nums[right] > nums[largest]:
                largest = right

            if largest != i:
                self.swapnum(nums, i, largest)
                max_heapify(nums, largest, size)

        l = len(nums)
        # 建堆,将初始序列建成一个大根堆
        build_maxheap(nums)
        for i in range(l - 1, 0, -1):
            # 将根节点(首元素)与最后一个元素交换
            self.swapnum(nums, 0, i)
            # 堆有序化, 让当前跟节点(首元素)值最大
            # 最后一个元素是最大的不参与后续排序了
            max_heapify(nums, 0, i)
        return nums


s = Solution()
nums = [2, 3, 5, 7, 9, 6, 4, 8, 1, 0]
for i in range(10):
    n = copy.deepcopy(nums)
    random.shuffle(n)
    print(s.bubblesort(n))
    print(s.selectsort(n))
    print(s.insertionsort(n))
    print(s.shellsort(n))
    print(s.quicksort(n, 0, len(nums) - 1))
    print(s.mergesort(n))
    print(s.heapsort(n))

求最长公共子序列

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m, n = len(text1), len(text2)
        dp = [[0] * (n + 1) for i in range(m + 1)]
        record = [[""] * (n + 1) for i 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
                    record[i][j] = record[i - 1][j - 1] + text1[i - 1]
                else:
                    # dp[i][j] = max(dp[i][j-1], dp[i-1][j])
                    if dp[i][j - 1] > dp[i - 1][j]:
                        dp[i][j] = dp[i][j - 1]
                        record[i][j] = record[i][j - 1]
                    else:
                        dp[i][j] = dp[i - 1][j]
                        record[i][j] = record[i - 1][j]
        print(record)
        print(dp)
        return dp[m][n]


if __name__ == "__main__":
    s = Solution()
    print(s.longestCommonSubsequence("asfdgfagfa", "daekcsagea"))
    # asaga

列举所有全排列

# -*- coding: utf-8 -*-

from typing import List

class Solution:
    # 通过回溯法——深度优先搜索(dfs)递归
    def permute(self, nums: List[int]) -> List[List[int]]:
        ret = []
        path = []

        def dfs(li):
            if len(li) == len(path):
                ret.append(path[:])
                return
            for i in li:
                if i not in path:
                    path.append(i)
                    dfs(li)
                    path.pop()

        dfs(nums)
        return ret

    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        ret = []
        path = []

        def dfs(lst, used):
            if len(lst) == len(path):
                ret.append(path[:])
                return
            for i in range(len(lst)):
                if used[i]:
                    continue
                if i > 0 and lst[i] == lst[i - 1] and not used[i - 1]:
                    continue
                used[i] = True
                path.append(lst[i])
                dfs(lst, used)
                used[i] = False
                path.pop()

        nums.sort()
        dfs(nums, [False] * len(nums))
        return ret

判断链表中是否有环

# -*- coding: utf-8 -*-

from typing import List

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

class Solution:
    # 龟兔赛跑,快慢指针
    def hasCycle(self, head: ListNode) -> bool:
        if not head or not head.next:
            return False
        
        slow = head
        fast = head.next

        while slow != fast:
            if not fast or not fast.next:
                return False
            slow = slow.next
            fast = fast.next.next
        
        return True

求最短路径

给定 N × N N \times N N×N的矩阵 A A A,其中 A [ i ] [ j ] A[i][j] A[i][j]表示相邻节点到达该点的距离。
每一步,都可以在上、下、左、右移动。
计算从[0,0] 到 [N-1, N-1] 最短路径。
即 求一条路径 [ 0 , 0 ] − > . . . − > [ N − 1 , N − 1 ] [0,0] -> ... ->[N-1, N-1] [0,0]>...>[N1,N1],使得 A [ 0 ] [ 0 ] + . . . + A [ N − 1 ] [ N − 1 ] A[0][0] + ...+ A[N-1][N-1] A[0][0]+...+A[N1][N1]最小。

def update(dist, i, j, a, b, c, d):
    # 更新dist
    if i > 0 and float("inf") != a and dist[i - 1][j] > a:
        dist[i - 1][j] = a
    if j > 0 and float("inf") != b and dist[i][j - 1] > b:
        dist[i][j - 1] = b
    if i < len(dist) - 1 and float("inf") != c and dist[i + 1][j] > c:
        dist[i + 1][j] = c
    if j < len(dist) - 1 and float("inf") != d and dist[i][j + 1] > d:
        dist[i][j + 1] = d
    return dist


def dijkstra(nums):
    length = len(nums)
    dist = [[float("inf")] * length for _ in range(length)]
    dist[0][0] = nums[0][0]
    done = [(0, 0)]
    i, j = 0, 0
    while i < length and j < length and dist[length - 1][length - 1] == float("inf"):
        a, b, c, d = float("inf"), float("inf"), float("inf"), float("inf")
        if i > 0:
            a = dist[i][j] + nums[i - 1][j]
        if j > 0:
            b = dist[i][j] + nums[i][j - 1]
        if i < length - 1:
            c = dist[i][j] + nums[i + 1][j]
        if j < length - 1:
            d = dist[i][j] + nums[i][j + 1]
        # 节点跳转
        if a < min(b, c, d) and (i - 1, j) not in done:
            dist[i - 1][j] = min(a, dist[i - 1][j])
            dist = update(dist, i, j, a, b, c, d)
            i -= 1
        elif b < min(c, d) and (i, j - 1) not in done:
            dist[i][j - 1] = min(b, dist[i][j - 1])
            dist = update(dist, i, j, a, b, c, d)
            j -= 1
        elif c < d and i < length - 1 and (i + 1, j) not in done:
            dist[i + 1][j] = min(c, dist[i + 1][j])
            dist = update(dist, i, j, a, b, c, d)
            i += 1
        elif j < length - 1 and (i, j + 1) not in done:
            dist[i][j + 1] = min(d, dist[i][j + 1])
            dist = update(dist, i, j, a, b, c, d)
            j += 1
        else:
            print("程序有问题,请检查!")
            break

        done.append((i, j))
        print(f"i: {i}, j: {j}")
        print(f"a: {a}, b: {b}, c: {c}, d: {d}")
        print(done)
        print(dist)
        # import pdb; pdb.set_trace();
    return i, j, dist[length - 1][length - 1]


print(
    dijkstra(
        [
            [1, 2, 32, 31, 30, 29, 28, 27],
            [33, 3, 4, 26, 25, 24, 23, 22],
            [34, 35, 5, 6, 7, 19, 20, 21],
            [36, 37, 38, 39, 8, 18, 16, 17],
            [43, 42, 41, 40, 9, 10, 15, 14],
            [44, 45, 46, 47, 48, 11, 49, 50],
            [51, 52, 53, 54, 55, 12, 13, 56],
            [57, 58, 59, 60, 61, 62, 14, 15],
        ]
    )
)

两个递增数列中查找数

已知数列 A A A由两个递增数列组成,即 A = a 1 , a 2 , … , a c , a c + 1 , … , a n A={a_1, a_2, \dots, a_c, a_{c+1}, \dots,a_n} A=a1,a2,,ac,ac+1,,an,其中 { a 1 , a 2 , … , a c } \{a_1, a_2, \dots, a_c\} {a1,a2,,ac} { a c + 1 , … , a n } \{a_{c+1}, \dots,a_n\} {ac+1,,an}是递增数列,且 a 1 > a n a_1>a_n a1>an。现在需要从 A A A中查找一个数。

# -*- coding: utf-8 -*-

import random


def find_num(A, target):
    # print(A)
    n = len(A)
    if n == 0:
        return -999
    if n == 1:
        return 0 if A[0] == target else -999
    m = n >> 1
    if A[0] > target:
        # A[0] > target,目标在第2段上,需要确定分割的位置
        if A[m] == target:
            return m
        elif A[m] > target:
            # A[m] > target,仍然需要确定分割的位置
            if A[m] > A[0]:
                # A[m] > A[0] > target,分割位置在m之后,目标在m之后
                return m + 1 + find_num(A[m + 1 : n], target)
            else:
                # target < A[m] < A[0],分割位置在m之前,又A[m] > target 目标在m之前
                return find_num(A[0:m], target)
        else:
            # A[m] < target < A[0], 故分割位置在m之前, 目标在m之后
            return m + 1 + find_num(A[m + 1 : n], target)
    else:
        # A[0] < target, 目标在第1段上,需要确定分割的位置
        if A[m] == target:
            return m
        elif A[m] > target:
            # A[m] > target > A[0], 故分割位置在第2段,但目标在m之前
            return find_num(A[0:m], target)
        else:
            # A[m] < target,仍然需要确定分割的位置
            if A[m] > A[0]:
                # target > A[m] > A[0],分割位置在m之后,目标在m之后
                return m + 1 + find_num(A[m + 1 : n], target)
            else:
                # A[m] < A[0] < target,分割位置在m之前,目标在m之前
                return find_num(A[0:m], target)


if __name__ == "__main__":
    for _ in range(1000):
        b = random.randint(1, 99)
        B = list(range(1, b + 1))
        a = random.randint(1, 99)
        A = list(range(b + 100, b + 100 + a + 1))
        C = A + B
        c = random.choice(C)
        print("C = ", C)
        print("c = ", c)
        print(find_num(C, c))

1-N中寻找缺失的数字

A A A是从 { 1 , 2 , … , n } \{1, 2, \dots, n\} {1,2,,n}中任意剔除一个数字后组成的数组,现需要寻找 A A A中缺失的数字

def findlostnum(nums, s=0, e=None):
    if e is None:
        e = len(nums) - 1
    l = e - s + 1
    # print(nums[s:e+1], l)
    
    if l == 0:
        return 1
    elif l == 1:
        return s+1 if nums[s] != s+1 else len(nums)+1
    m = (l-1) >> 1
    
    if nums[m + s] > m + s + 1:
        return findlostnum(nums, s, m + s)
    else:
        return findlostnum(nums, m + s + 1, e)

print(findlostnum([2,3,4,5,6])==1)
print(findlostnum([1,3,4,5,6])==2)
print(findlostnum([1,2,4,5,6])==3)
print(findlostnum([1,2,3,5,6])==4)
print(findlostnum([1,2,3,4,6])==5)
print(findlostnum([1,2,3,4,5])==6)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值