剑指offer - 题64~67(滑动窗口最大值,矩阵路径,机器人运动,剪绳子,最大乘积)

41 篇文章 0 订阅
25 篇文章 0 订阅

滑动窗口的最大值
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。

# -*- coding:utf-8 -*-
# -*- coding:utf-8 -*-
class Solution:
    def maxInWindows(self, num, size):
        # write code here
        res=[]
        if not size or len(num)<size or not num:
            return res
        # 暴力解法:
        for i in range(0,len(num)-size+1):
            temp_arr=num[i:i+size]
            max_value=temp_arr[0]
            for j in temp_arr:
                if j>max_value:
                    max_value=j
            res.append(max_value)
        return res
        # 比较大小时不重复计算,使用队列:
        '''
        双向队列的方法,队列只存最大值 和依次小于最大值的元素的坐标
        在队列首部存放当前最大值的坐标,如果后续加进来的元素比现在的队尾元素小,则加入
        如果当前队尾的元素 比要加入的新元素小,则移除这些队尾元素
        如果当前坐标i+1>=size说明 窗口已经覆盖了三个元素以上,可以拿最大值了
        将队列从尾部开始小于新加入元素的元素坐标都移除,因为此时他们已经不可能是窗口最大值了
        队首元素的有效期即它为最大元素的窗口,是在他的坐标index +size区间内,超过这个区间就移除掉这个当前最大值 即当前队首元素
        当i+1<size时候说明窗口还没覆盖到3个元素,还没找到窗口覆盖的最大值
        '''      
        from collections import deque
        deq = deque([0])
        for i in range(1,len(num)):
            if i - deq[0] >= size:
                deq.popleft()
            if num[i] > num[deq[0]]:
                deq = deque([i])
            else:
                while num[i] > num[deq[-1]]:
                    deq.pop()
                deq.append(i)
            if i >= size-1:
                res.append(num[deq[0]])
        return res

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

# -*- coding:utf-8 -*-
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        for i, s in enumerate(matrix):
            # 当字符串第一个字符与矩阵中元素匹配上时,开始匹配下一个,其中i//cols和i%cols是匹配到的第一个字符的行列索引值
            if s==path[0] and self.visit([(i//cols, i%cols)], matrix, rows, cols, path):
                return True
        return False
     
    def visit(self, ans, matrix, rows, cols, path):
        # 如果ans中存储的已经匹配道德字符个数等于字符串的长度,则说明已经匹配完毕,返回True
        if len(ans)==len(path):
            return True
        i,j = ans[-1]
        # 匹配当前元素上下左右的元素是否与path下一元素相匹配
        nex = [(ii,jj) for ii,jj in [(i,j-1),(i,j+1),(i-1,j),(i+1,j)]
               if 0<= ii <rows and 0<= jj <cols and 
               (ii,jj) not in ans and
               matrix[ii*cols +jj]==path[len(ans)]]
        # 对于所有满足条件的元素都要分别进行下一次匹配
        return sum([self.visit(ans+[x], matrix, rows, cols, path) for x in nex])

机器人的运动范围
地上有一个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 __init__(self):
        self.res=0
        
    def movingCount(self, threshold, rows, cols):
        # write code here
        # 首先将方格中所有位置赋值1
        arr = [[1 for i in range(cols)] for j in range(rows)]
        self.findway(arr, 0, 0, threshold)
        return self.res
    
    def findway(self, arr, i, j, k):
        # 当数组行列下标超出范围时,跳出该方法
        if i < 0 or j < 0 or i >= len(arr) or j >= len(arr[0]):
            return
        # 将行列坐标每一个数位都转化为int类型的数字,便于求和
        tmpi = list(map(int, list(str(i))))
        tmpj = list(map(int, list(str(j))))
        if sum(tmpi) + sum(tmpj) > k or arr[i][j] != 1:
            return
        # 满足条件即赋值0
        arr[i][j] = 0
        self.res += 1
        # 对上下左右进行判断
        self.findway(arr, i + 1, j, k)
        self.findway(arr, i - 1, j, k)
        self.findway(arr, i, j + 1, k)
        self.findway(arr, i, j - 1, k)

剪绳子
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:

输入一个数n,意义见题面。(2 <= n <= 60)

输出描述:

输出答案。

示例1
输入

8

输出

18
# -*- coding:utf-8 -*-
class Solution:
    def cutRope(self, number):
        # write code here
        res=1
        if number<=1:
            return 0
        elif number<=2:
            return 1
        elif number<=3:
            return 2
        # 法一:数学归纳法/贪心算法
        elif number>3:
            if number%3==0:
                res=3**(number//3)
            elif number%3==1:
                res=3**(number//3-1)*4
            else:
                res=3**(number//3)*(number%3)
        return res
        # 法二:动态规划
        prod=[0,1,2,3]
        for i in range(4,number+1):
            max=0
            for j in range(1,i//2+1):
                pro=prod[j]*prod[i-j]
                if pro>max:
                    max=pro
            prod.append(max)
        return prod[number]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值