左神中级提升班4(Python)

本文介绍了四个编程问题的解题思路,包括分配物品的packing_machine函数、矩阵打印边界数字的Print函数、矩阵顺时针/逆时针旋转的rotate90函数以及找出字符串中出现频率最高的前k个元素的zigzag和top_k_frequent函数。
摘要由CSDN通过智能技术生成

题目1:解题思路:

分别计算左边和右边是多出了物品还是少物品了,再进行分析:

1.左边和右边都是负数,那就是需要往左边和右边扔物品,但每次只能扔一个,所以需要把左边和右边加起来;

2.左边和右边都是正数,那就是左边和右边都需要往中间扔,由于左边和右边可以同时往里扔,所以取左右中的最大值即可;

3.左边是负数右边是正数,那就是中间需要往左边扔,然后右边往中间扔,也是可以同时进行的,取最大值即可,左正右负同理;

结论:求每个位置的至少轮次是多少,最大的那就是就是答案。 

def packing_machine(arr):
    N = len(arr)
    if N == 0: return -1
    Sum = sum(arr)
    if Sum%N != 0: return -1 # 如果不能被整除,每台机器上的数量不可能相等
    leftSum = 0
    avg,ans = Sum/N, float('-inf')
    for i in range(N):
        # 负数则为左边缺少多少,正数则为多出了多少
        leftRest = leftSum - i*avg
        # 负数则为右边缺少多少,正数则为多出了多少
        rightRest = Sum - leftSum - arr[i] - (N-1-i)*avg
        if leftRest < 0 and rightRest < 0:
            # 左右皆负,至少需要|左|+|右|
            ans = max(ans, abs(leftRest)+abs(rightRest))
        else:
            # 其它至少需要max(|左|,|右|)
            ans = max(ans, max(abs(leftRest), abs(rightRest)))
        leftSum += arr[i]
    return ans

arr = [1,0,5]
result = packing_machine(arr)
print('packing_machine:', result)

题目2:

解题思路:

定义一个函数,给定左上角点和右下角点,依次打印从左上角的点到右下角的点的边界数字,最后再把左上角和右下角的点往中间移动。        

def Print(arr):
    def Printrotate(a, b, c, d):
        if a == c:
            for i in range(b, d + 1):
                print(arr[a][i], end=',')
        elif b == d:
            for i in range(a, c + 1):
                print(arr[i][b], end=',')
        else:
            curC, curR = b, a
            while curC!=d:
                print(arr[a][curC], end=',')
                curC+=1
            while curR!=c:
                print(arr[curR][d], end=',')
                curR+=1
            while curC!=b:
                print(arr[c][curC], end=',')
                curC-=1
            while curR!=a:
                print(arr[curR][b], end=',')
                curR-=1
    N, M = len(arr), len(arr[0])
    a, b, c, d = 0, 0, N-1, M-1
    while a <= c and b <= d:
        Printrotate(a, b, c, d)
        a += 1
        b += 1
        c -= 1
        d -= 1

arr = [[1,2,3,4],[10,11,12,5],[9,8,7,6]]
Print(arr)

 题目三:

def rotate90(arr):
    def pre(a, b, c, d):
        for i in range(d-b):
            tmp = arr[a][b+i]
            arr[a][b+i] = arr[c-i][b]
            arr[c-i][b] = arr[c][d-i]
            arr[c][d-i] = arr[a+i][d]
            arr[a+i][d] = tmp
    a, b, c, d = 0, 0, len(arr) - 1, len(arr[0]) - 1
    while a < c:
        pre(a,b,c,d)
        a+=1
        b+=1
        c-=1
        d-=1
    return arr

arr = [[1,2,3],[1,2,3],[1,2,3]]
rotate90(arr)

题目4:

解题思路:

def zigzag(arr):
    def print1(ar, ac, br, bc, fromup):
        if fromup:
            while br != ar-1:
                print(arr[br][bc], end=',')
                br-=1
                bc+=1
        else:
            while ar != br+1:
                print(arr[ar][ac], end=',')
                ar+=1
                ac-=1
    ar, ac, br, bc = 0, 0, 0, 0
    endR, endC = len(arr)-1, len(arr[0])-1
    fromup = True
    while ar < endR + 1:
        print1(ar, ac, br, bc, fromup)
        ar = ar + 1 if ac == endC else ar
        ac = ac if ac == endC else ac + 1
        bc = bc + 1 if br == endR else bc
        br = br if br == endR else br + 1
        fromup = False if fromup else True

arr = [[1,2,6],[3,5,7],[4,8,9]]
zigzag(arr)

题目5:给定一个字符串类型的arr,求其中出现最多的前k个。

解题思路:1.先遍历arr,得到每个字符串出现的次数,python可以用collections里的库实现。

                  2.放入最大堆中,输出前面k个即可。

from collections import Counter
import heapq
def top_k_frequent(words, k):
    # 创建字典计数
    word_count = Counter(words)
    # 创建一个最小堆 在堆中是基于元组的第一个元素排序的
    heap = [(-count, word) for word, count in word_count.items()]
    # 由于heapq模块是最小堆,前面加个负数即可实现最大堆
    heapq.heapify(heap)
    # 取前面k个
    top_k = [heapq.heappop(heap)[0] for _ in range(k)]
    return top_k

words_array = ["apple", "banana", "orange", "apple", "banana", "apple", "grape"]
k = 2
result = top_k_frequent(words_array, k)
print(result)

 

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值