备战菊厂笔试4

目录

39.组合总和

回溯(单向剪枝)

3102.最小化曼哈顿距离

利用曼哈顿距离的性质

3163.压缩字符串3

46.全排列

53.最大子数组和


39.组合总和

39. 组合总和

注意:

set不能添加list得加元组

元组不可修改

sorted后得赋值

python 复制代码
class Solution:
    def combinationSum(self, candidates,target):

        ans=set()
        def fenjie(num,se):
            if num==0:
                se=tuple(sorted(se))
                ans.add(se)
                return
            if num<0:
                return
            
            for i in candidates:
                se2=tuple(list(se)+[i])
                fenjie(num-i,se2)

        fenjie(target,())
        return [list(x) for x in ans]  # 转换为题目要求的格式
if __name__=='__main__':
    candidates = [2,3,6,7];target = 7

    sol=Solution()
    ans=sol.combinationSum(candidates,target)
    print(ans)

虽然过了,但这道题更好的办法是

回溯(单向剪枝)

回溯是一种 试探+撤销 的策略

我们将这问题看成一颗搜索树,每个节点表示一种选择路径,那么我们从根节点开始一步步试探性地往下走,直到走到满足条件的叶子节点 ,那么就把路径加入答案

我们用start控制开始下标,单向(升序)地往后面选(注意同一个数字可以重复使用,那么下一层就是从当前start开始

python 复制代码
start=0, path=[], remaining=7
├── 选2 → path=[2], remaining=5
│   ├── 选2 → path=[2,2], remaining=3
│   │   ├── 选2 → path=[2,2,2], remaining=1
│   │   │   └── 选2 → path=[2,2,2,2], remaining=-1 ❌ 超了,返回
│   │   │   └── 选3 → path=[2,2,2,3], remaining=-2 ❌ 超了,返回
│   │   ├── 选3 → path=[2,2,3], remaining=0 ✅ 找到结果
│   │   └── ...
│   └── 选3 → path=[2,3], remaining=2
├── 选3 → path=[3], remaining=4
│   ├── 选3 → path=[3,3], remaining=1
│   └── ...
├── 选6 → path=[6], remaining=1
├── 选7 → path=[7], remaining=0 ✅ 找到结果
python 复制代码
class Solution:
    def combinationSum(self, candidates, target):
        res = []
        candidates.sort()

        def backtrack(start, path, remaining):
            if remaining == 0:
                res.append(path[:])  # 找到一个合法组合,加入结果
                return
            if remaining < 0:
                return  # 超过了目标值,剪枝

            for i in range(start, len(candidates)):
                path.append(candidates[i])
                backtrack(i, path, remaining - candidates[i])  # 可重复选,从 i 开始
                path.pop()  # 撤销上一步选择,继续尝试下一个
                
        backtrack(0, [], target)
        return res

其中 path,pop() 有点像 恢复vis[ ] = 0

3102.最小化曼哈顿距离

3102. 最小化曼哈顿距离

本来我想用一半的二维矩阵来优化空间复杂度,但是这样反而得不偿失了,太绕了 连正确答案都跑不出来,还是正常用二维的

这题的主要思路的思路就是枚举删的点,然后再枚举所有点的所有边(除去当时删的点的),进行表示

python 复制代码
'''
class Solution:
    def minimumDistance(self, points):
        n=len(points)
        ma=[[0]*i for i in range(n-1,0,-1)]
        for i in range(n-1):
            for j in range(i+1,n):
                dis=abs(points[i][0]-points[j][0])+abs(points[i][1]-points[j][1])
                ma[i][j-i-1]=dis
        print(ma)

        ans=float('inf')
        for i in range(n):#去掉的点
            now=-1
            for j in range(n):#除去掉的点外的点出发到其他点的距离
                if j==i:
                    continue
                else:
                    for a in range(n-j-1):
                        if a+1==i:continue
                        now=max(now,ma[j][a])
                    for b in range(j):
                        if b==i:continue
                        now=max(now,ma[b][j-b-1])
                    ans=min(ans,now)
        return ans
'''
class Solution:
    def minimumDistance(self, points):
        import itertools
        n = len(points)
        ans = float('inf')
        for skip in range(n):  # 枚举删除哪一个点
            max_dist = 0
            remaining = [points[i] for i in range(n) if i != skip]
            for i in range(len(remaining)):
                for j in range(i + 1, len(remaining)):
                    x1, y1 = remaining[i]
                    x2, y2 = remaining[j]
                    dist = abs(x1 - x2) + abs(y1 - y2)
                    max_dist = max(max_dist, dist)
            ans = min(ans, max_dist)
        return ans
if __name__=='__main__':
    points=[[3,10],[5,15],[10,2],[4,4]]

    sol=Solution()
    ans=sol.minimumDistance(points)
    print(ans)
        

但是这样暴力肯定会TLE

利用曼哈顿距离的性质

python 复制代码
class Solution:
    def minimumDistance(self, points):
        n = len(points)
        vals = [[] for _ in range(4)]  # 保存四种变换

        for i, (x, y) in enumerate(points):
            vals[0].append((x + y, i))
            vals[1].append((x - y, i))
            vals[2].append((-x + y, i))
            vals[3].append((-x - y, i))

        candidates = set()
        for arr in vals:
            arr.sort()
            candidates.add(arr[0][1])     # 最小值对应点
            candidates.add(arr[-1][1])    # 最大值对应点

        def get_max_dist(skip):
            max_val = 0
            for arr in vals:
                temp = [(val, idx) for val, idx in arr if idx != skip]
                max_val = max(max_val, temp[-1][0] - temp[0][0])
            return max_val

        return min(get_max_dist(i) for i in candidates)

3163.压缩字符串3

3163. 压缩字符串 III

主要用到 strip

python 复制代码
class Solution:
    def compressedString(self, word: str) -> str:
        comp=''
        l=len(word)
        while word:
            '''
            i=0
            while word[i]==word[i+1]:#前缀
                i+=1
            comp+=str(i+1)+word[i]
            '''
            c=word[0]
            
            word=word.lstrip(c)# lstrip :  删除左边连续子串直到碰到其他字符
            #print(word)
            l2=len(word)
            d=l-l2
            if d>9:
                d1=d//9
                d2=d%9
                comp+=('9'+c)*d1
                if d2:
                    comp+=str(d2)+c
            else:
                comp+=str(d)+c
            l=l2
        return comp

if __name__=='__main__':
    word='abcde'

    sol=Solution()
    ans=sol.compressedString(word)
    print(ans)

灵神的代码

其中enumerate是同时提取索引和元素(素数筛里面用的也是enumerate)

divmod( a,b )返回( a//b,a%b )

python 复制代码
class Solution:
    def compressedString(self, word: str) -> str:
        t = []
        i0 = -1
        for i, c in enumerate(word):
            if i + 1 == len(word) or c != word[i + 1]:
                k, rem = divmod(i - i0, 9)
                t.append(("9" + c) * k)
                if rem:
                    t.append(str(rem))
                    t.append(c)
                i0 = i
        return ''.join(t)

作者:灵茶山艾府
链接:https://leetcode.cn/problems/string-compression-iii/solutions/2790666/mo-ni-pythonjavacgo-by-endlesscheng-3hk7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

46.全排列

注意itertools.permutations出来的是元组,得list

python 复制代码
from itertools import permutations

class Solution:
    def permute(self, nums):
        l=len(nums)
        ans=permutations(nums,l)
        lis=[]
        for i in ans:
            lis.append(list(i))
        return lis

if __name__=='__main__':
    nums=[1,2,3]

    sol=Solution()
    ans=sol.permute(nums)
    print(ans)

53.最大子数组和

我的第一想法是用前缀和之差,于是我直接暴力表示了

python 复制代码
class Solution:
    def maxSubArray(self, nums):
        pre=[[0,0]]
        l=len(nums)

        for i,k in enumerate(nums):
            #print(i,k)
            pre.append([pre[-1][0]+k,pre[-1][1]+1])
        
        #print(pre)

        ans=-float('inf')
        for su,n in pre:
            for j in range(n):
                now=su-pre[j][0]
                ans=max(ans,now)
        return ans
            

if __name__=='__main__':
    nums=[-2,1,-3,4,-1,2,1,-5,4]

    sol=Solution()
    ans=sol.maxSubArray(nums)
    print(ans)

因为 最大值= -最小值,所以我们其实可以在一边遍历数组计算前缀和的同时一边维护前缀和的最小值

请注意,由于题目要求子数组不能为空,应当先计算前缀和-最小前缀和,再更新最小前缀和。相当于不能在同一天买入股票又卖出股票。如果先更新最小前缀和,再计算前缀和-最小前缀和,就会把空数组的元素和 0 算入答案。(来自灵神)

python 复制代码
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        ans = -inf
        min_pre_sum = pre_sum = 0
        for x in nums:
            pre_sum += x  # 当前的前缀和
            ans = max(ans, pre_sum - min_pre_sum)  # 减去前缀和的最小值
            min_pre_sum = min(min_pre_sum, pre_sum)  # 维护前缀和的最小值
        return ans
相关推荐
.格子衫.1 小时前
真题卷001——算法备赛
算法
学地理的小胖砸1 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
安迪小宝1 小时前
6 任务路由与负载均衡
运维·python·celery
XiaoyaoCarter1 小时前
每日一道leetcode
c++·算法·leetcode·职场和发展·二分查找·深度优先·前缀树
Blossom.1181 小时前
使用Python实现简单的人工智能聊天机器人
开发语言·人工智能·python·低代码·数据挖掘·机器人·云计算
lisw051 小时前
Python高级进阶:Vim与Vi使用指南
python·vim·excel
Hygge-star1 小时前
【数据结构】二分查找5.12
java·数据结构·程序人生·算法·学习方法
ayiya_Oese1 小时前
[模型部署] 3. 性能优化
人工智能·python·深度学习·神经网络·机器学习·性能优化
SoraLuna1 小时前
「Mac畅玩AIGC与多模态40」开发篇35 - 用 Python 开发服务对接 SearxNG 与本地知识库
python·macos·aigc
noravinsc2 小时前
redis是内存级缓存吗
后端·python·django