Dongxing's Wiki Dongxing's Wiki
首页
  • 剑指 Offer
  • LeetCode
  • 算法与数据结构
  • Python 语言
  • Web 开发
  • Hive
  • Elastic Search
  • 机器学习
  • NLP
  • 检索技术
  • 数据分析
  • 经验笔记
  • Linux 配置
  • 博客进化记
  • 杂谈
GitHub (opens new window)
首页
  • 剑指 Offer
  • LeetCode
  • 算法与数据结构
  • Python 语言
  • Web 开发
  • Hive
  • Elastic Search
  • 机器学习
  • NLP
  • 检索技术
  • 数据分析
  • 经验笔记
  • Linux 配置
  • 博客进化记
  • 杂谈
GitHub (opens new window)
  • 剑指offer

    • 剑指 Offer - python 题解
    • 剑指Offer(1)
    • 剑指Offer(2)
    • 剑指Offer(3)
    • 剑指Offer(4)
    • 剑指Offer(5)
    • 剑指Offer(6)
    • 剑指Offer(7)
    • 剑指Offer(8)
    • 剑指Offer(9)
    • 剑指Offer(10)
    • 剑指Offer(11)
    • 剑指Offer(12)
    • 剑指Offer(13)
    • 剑指Offer(14)
    • 剑指Offer(15)
      • 滑动窗口的最大值
        • 问题
        • 思路
        • 代码
      • 矩阵中的路径
        • 问题
        • 思路
        • 代码
      • 机器人的运动范围
        • 问题
        • 思路
        • 代码
  • 剑指Offer
  • 剑指offer
anthony
2018-10-12
目录

剑指Offer(15)

更新:此题解 markdown 源文件已放到 Github https://github.com/bytetopia/offer-coding-interviews-python (opens new window),欢迎前去给个小星星鸭!


# 滑动窗口的最大值

# 问题

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

# 思路

详细思路可参照 https://blog.csdn.net/qq_41822235/article/details/82891762

基本思路,从左到右滑过每个窗口,在每个窗口里寻找最大值并记录下来。一点改进,诸如记住当前最大值的下标,到新窗口里,如果根据下标判断该最大值仍然在新窗口,则只比较新窗口比上一个窗口新加入的那1个元素和最大值的大小,如果不在的话则要找遍新窗口才能找出最大,可以减少一些比较次数。

上面方法需要比较的次数是 size x n,可以进一步减少比较次数。

滑动窗口可以用一个队列来记录,新值进入窗口则加入队列,旧值滑出窗口则移出队列。但这里采用可以从两端删除元素的队列,来减少比较次数。目的是,队列头部始终存储队列中最大的元素。

当新的元素到来时,首先判断队尾元素是否比它小,若小,则剔除当前队尾元素,一直重复下去,直到队尾元素比新元素大,或者队列空了。然后新值加到队尾。然后判断当前队头是否下标超出窗口,如果超出,则队头移出。完成上述操作后,当前队头就是当前窗口的最大值。

# 代码

按基本思路(size x n)

# -*- coding:utf-8 -*-
class Solution:
    def maxInWindows(self, num, size):
        # write code here
        length = len(num)
        if size <= 0 or size > length:
            return []
        i = 0
        ans =[max(num[:size])]
        while size + i < length:
            if num[i] < ans[-1]:
                ans.append(max([ans[-1], num[i+size]]))
            else:
                ans.append(max(num[i+1:i+size+1]))
            i += 1
        return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

双向队列写法:

# -*- coding:utf-8 -*-
class Solution:
    def maxInWindows(self, num, size):
        # write code here
        ans = []
        length = len(num)
        if size <= 0 or size > length or not num:
            return []
        deque = []  # 队列里存的是下标
        for i in range(0, len(num)):
            while(deque and num[deque[-1]] < num[i]):
                deque.pop()
            deque.append(i)
            if i - deque[0] + 1 > size:
                deque.pop(0)
			if i >= k - 1:
            	ans.append(num[deque[0]])
        return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 矩阵中的路径

# 问题

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

# 思路

使用回溯法。首先遍历全部数据,找到和字符串第一个字符相同的位置,以此为起点,上下左右前进寻找和下一个字符相同的位置行。如果某处上下左右都找不到,则回退到上一步。非常适合使用递归的思路,而且代码也比较容易懂,详见下面代码(这段没有自己写,直接搬运了一份)。

# 代码

# -*- coding:utf-8 -*-
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        if not matrix and rows <= 0 and cols <= 0 and path == None:
            return False
        # 模拟的字符矩阵
        markmatrix = [0] * (rows * cols)
        pathlength = 0
        # 从第一个开始递归,当然第一二个字符可能并不位于字符串之上,所以有这样一个双层循环找起点用的,一旦找到第一个符合的字符串,就开始进入递归,
        # 返回的第一个return Ture就直接跳出循环了。
        for row in range(rows):
            for col in range(cols):
                if self.hasPathCore(matrix, rows, cols, row, col, path, pathlength, markmatrix):
                    return True
        return False

    def hasPathCore(self, matrix, rows, cols, row, col, path, pathlength, markmatrix):
        # 说明已经找到该路径,可以返回True
        if len(path) == pathlength:
            return True

        hasPath = False
        if row >= 0 and row < rows and col >= 0 and col < cols and matrix[row * cols + col] == path[pathlength] and not \
                markmatrix[row * cols + col]:
            pathlength += 1
            markmatrix[row * cols + col] = True
            # 进行该值上下左右的递归
            hasPath = self.hasPathCore(matrix, rows, cols, row - 1, col, path, pathlength, markmatrix) \
                      or self.hasPathCore(matrix, rows, cols, row, col - 1, path, pathlength, markmatrix) \
                      or self.hasPathCore(matrix, rows, cols, row + 1, col, path, pathlength, markmatrix) \
                      or self.hasPathCore(matrix, rows, cols, row, col + 1, path, pathlength, markmatrix)

            # 对标记矩阵进行布尔值标记
            if not hasPath:
                pathlength -= 1
                markmatrix[row * cols + col] = False
        return hasPath
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 机器人的运动范围

# 问题

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

# 思路

思路仍然是回溯法,但判断条件有了变化。

# 代码

# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        markmatrix = [False] * (rows * cols)
        count = self.GetNum(threshold, rows, cols, 0, 0, markmatrix)
        return count

    def GetNum(self, threshold, rows, cols, row, col, markmatrix):
        count = 0

        if self.GetSum(threshold, rows, cols, row, col, markmatrix):
            markmatrix[row * cols + col] = True
            count = 1 + self.GetNum(threshold, rows, cols, row - 1, col, markmatrix) + \
                    self.GetNum(threshold, rows, cols, row, col - 1, markmatrix) + \
                    self.GetNum(threshold, rows, cols, row + 1, col, markmatrix) + \
                    self.GetNum(threshold, rows, cols, row, col + 1, markmatrix)
        return count

    def GetSum(self, threshold, rows, cols, row, col, markmatrix):
        if row >= 0 and row < rows and col >= 0 and col < cols and self.getDigit(row) + self.getDigit(
                col) <= threshold and not markmatrix[row * cols + col]:
            return True
        return False

    def getDigit(self, number):
        sumNum = 0
        while number > 0:
            sumNum += number % 10
            number = number // 10
        return sumNum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
上次更新: 2020/09/19, 22:09:00
剑指Offer(14)

← 剑指Offer(14)

Theme by Vdoing | Copyright © 2017-2023 anthony 京ICP备17072417-3
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式