《剑指offer—算法篇》题解—Python实现

本文详细介绍了《剑指offer》中涉及的排序、回溯、动态规划、斐波那契数列、查找、位运算、全排列等算法的Python解法,并通过代码示例进行说明,帮助读者理解和掌握这些经典算法。
摘要由CSDN通过智能技术生成

本篇博客介绍算法部分,涉及的算法有排序、回溯、动态规划、斐波那契数列、查找、位运算、全排列,还涉及数学知识、规律总结和扩展思维题目。

六、排序篇(2道题)

涉及内容:数组中的逆序对 (归并排序)

                    最小的K个数(快速排序等)

42.最小的K个数

题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

思路:按照各种排序算法,找到排序结果的前K个数。

代码:

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        #快速排序
        #还有其它的排序方法,详见
        #https://www.nowcoder.com/questionTerminal/6a296eb82cf844ca8539b57c23e6e9bf?f=discussion
        def quick_sort(lst):
            if not lst:
                return []
            pivot = lst[0]
            left = quick_sort([x for x in lst[1: ] if x < pivot])
            right = quick_sort([x for x in lst[1: ] if x >= pivot])
            return left + [pivot] + right
         
        if tinput == [] or k > len(tinput):
            return []
        tinput = quick_sort(tinput)
        return tinput[: k]

43. 数组中的逆序对

题目描述:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出, 即输出P%1000000007。

思路:逆序对的个数等于完成由小到大排序数字时,数字两两之间交换的次数。

代码:

# -*- coding:utf-8 -*-
def MergeElem(data, start, mid, end, temp):  # data[start...mid], data[mid+1...end]
    cnt = 0
    i = start
    j = mid + 1
    k = start
    while i <= mid and j <= end:
        if data[j] < data[i]:  # data[start...i...mid] data[mid+1...j...end]
            temp[k] = data[j]
            cnt += j - k
            j += 1
            k += 1
        else:
            temp[k] = data[i]
            i += 1
            k += 1
    while i <= mid:
        temp[k] = data[i]
        i += 1
        k += 1
    while j <= end:
        temp[k] = data[j]
        j += 1
        k += 1
    data[start:end+1] = temp[start:end+1]
    return cnt

def InverseCore(data, start, end, temp):
    cnt = 0
    if start < end:
        mid = (start + end) // 2
        cnt += InverseCore(data, start, mid, temp)
        cnt += InverseCore(data, mid+1, end, temp)
        cnt += MergeElem(data, start, mid, end, temp)
    return cnt

class Solution:
    #归并排序
    def InversePairs(self, data):
        # write code here
        temp = data[:]
        count = InverseCore(data, 0, len(data)-1, temp)
        return count%1000000007

七、回溯法(2道题)

涉及内容:矩阵中的路径

                 机器人的运动范围                   

44、矩阵中的路径

题目描述:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

思路:从任意结点开始,任选该结点的某一个方向,判断结点在某一方向的值是否等于路径中的数值。确定每一步都是正确的情况下,再考虑下一步,这也和“广度优先遍历”是类似的。

代码:

# -*- coding:utf-8 -*-
def BFS(matrix, row, col, path, visited):
    if row < 0 or row >= len(matrix) or col < 0 or col >= len(matrix[0]) or visited[row][col]: 
        return False
    if path[0] == matrix[row][col]:
        if len(path) == 1:
            return True
        visited[row][col] = 1
        if BFS(matrix, row+1, col, path[1:], visited) or \
            BFS(matrix, row-1, col, path[1:], visited) or \
            BFS(matrix, row, col-1, path[1:], visited) or \
            BFS(matrix, row, col+1, path[1:], visited):
            return True
        return False
    else:
        return False
    
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        array = list(matrix)
        array = [array[i*cols:(i+1)*cols] for i in range(rows)]
        for i in range(rows):
            for j in range(cols):
                visited = [[0] * len(array[0]) for _ in range(len(array))]
                if BFS(array, i, j, list(path), visited): 
                    return True
        return False

45. 机器人的运动范围

题目描述:地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

思路:和第34题类似,也是要判断每一步是否满足格子的横纵坐标和的不等式约束。

代码:

# -*- coding:utf-8 -*-
def getN(i, j):
    res = 0
    while i:
        res += (i % 10)
        i //= 10
    while j:
        res += (j % 10)
        j //= 10
    return res

def DFS(array, i, j, threshold, visited):
    if i<0 or j<0 or i>len(array)-1 or j>len(array[0])-1 or array[i][j]>threshold or visited[i][j]:
        return 0
    res = 1
    visited[i][j] = 1
    res += DFS(array, i+1, j, threshold, visited)
    res += DFS(array, i-1, j, threshold, visited)
    res += DFS(array, i, j+1, threshold, visited)
    res += DFS(array, i, j-1, threshold, visited)
    return res

class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        array = []
        for i in range(rows):
            re
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值