Codility每周一课:P91.1 RectangleBuilderGreaterArea

版权声明:AnFany https://blog.csdn.net/qq_32882309/article/details/88714946

0.png

P91.1 RectangleBuilderGreaterArea
Count the distinct rectangle sizes, of area greater than or equal to X, that can be built out of a given set of segments.

  • P91.1 建立矩形
    计算面积不小于X的不同矩形的个数

哈夫林·伍利·普罗德霍夫是一位杰出的牧羊人。他想为他的羊群新建一个矩形围栏,围栏恰好是由四块栅栏构成(也就是说,围栏相对边的栅栏的长度是一样的)。伍利可以从他谷仓里的N块篱笆中选择这些栅栏。为了容纳整群羊,围栏的面积必须大于或等于给定的阈值X。

伍利对他能用多少种不同的方法造围栏很感兴趣。如果围栏的边长不同,即使面积一样,也认为它们是不同的。例如,面积为1×4的围栏与面积为2×2的围栏不同(尽管两者的面积都为4),但面积为1×2和2×1的围栏则被认为是相同的。

编写函数:

def solution(A, X)

给定一个包含N个整数(表示栅栏的长度)的数组A和一个整数X,则返回构建满足上述条件的矩形围栏的不同方法的数目。如果结果超过1,000,000,000,函数应返回−1。

例如,给定X=5和以下数组A:A[0]=1,A[1]=2,A[2]=5,A[3]=1,A[4]=1,A[5]=2,A[6]=3,A[7]=5,A[8]=1。

image

上图显示了可用的栅栏(左侧)和可以建造成的围栏(右侧)。这些围栏的面积分别是1×5和2×5。虽然也可以建造面积为1×1和1×2的围栏,但面积不符合要求。另外,不可能建造面积为2×3或3×5的围栏,因为只有一块长度为3的栅栏。因此针对示例,函数应该返回2。

假定:

  1. N是区间[0,100,000]内的整数;
  2. X是区间[1,1,000,000,000]内的整数;
  3. 数组A的每个元素都是区间[1,1,000,000,000]内的整数;
  • 解题思路

首先统计各个长度栅栏的数量,最后只存储数量不小于2的栅栏,并且按照栅栏的长度升序排列。然后遍历栅栏列表,对于长度为s的栅栏,利用二分查找算法,此时需要注意栅栏s的个数是否不小于4,如果否的话,说明不能只用长度为s的构成围栏,因此起始的索引需要在s的索引上加1。如果是的话,则起始的索引就是s的索引。找到第一个和s构成的面积满足条件的栅栏的索引后,说明此索引以后的栅栏均满足条件。

  • Python3代码
# -*- coding:utf-8 -*-
# &Author  AnFany
# Lesson 91:Tasks from Indeed Prime 2016 challenge
# P 91.1 RectangleBuilderGreaterArea


def solution(A, X):
    """
    利用数组A中的元素,构建面积不小于X的不同矩形的个数
    :param A: 数组
    :param X: 面积阈值
    :return: 满足条件的矩形的个数
    """
    count_item = {}
    for i in A:
        if i in count_item:
            count_item[i] += 1
        else:
            count_item[i] = 1

    no_less_than_2 = [j for j in count_item if count_item[j] >= 2]  # 出现次数大于等于2的存储下来

    ordered_list = sorted(no_less_than_2)  # 按照栅栏的长度升序排序

    length = len(ordered_list)  # 可用栅栏的个数

    if not length:  # 没有可用的栅栏
        return 0
    else:
        if length == 1:  # 只有一种长度的栅栏,只有栅栏数不小于4时,才可以建立围栏
            if count_item[ordered_list[0]] >= 4:
                return 1
            else:
                return 0
        else:
            sum_count = 0  # 记录总的个数
            for index, value in enumerate(ordered_list):
                if count_item[value] >= 4:
                    start = index    # 如果用一种长度的栅栏,其数量需要不小于4
                else:
                    start = index + 1
                end = length - 1
                #  开始二分查找算法
                while start <= end:
                    middle = int((start + end) / 2)
                    if ordered_list[middle] * value >= X:
                        end = middle - 1
                    else:
                        start = middle + 1
                sum_count += length - end - 1
                if sum_count > 1e9:
                    return -1
            return sum_count
  • 结果
    image

点击获得更多编程练习题。欢迎Follow,感谢Star!!! 扫描关注微信公众号pythonfan,获取更多。

image

image

猜你喜欢

转载自blog.csdn.net/qq_32882309/article/details/88714946