当前位置: 首页 > 面试题库 >

生成独特的,有序的勾股三胞胎

鲁涵意
2023-03-14
问题内容

这是我编写的用于计算勾股三胞胎的程序。当我运行该程序时,由于使用if语句,它会将每组三胞胎打印两次。有什么办法可以让我的程序只打印一组新的三胞胎一次?谢谢。

import math

def main():
    for x in range (1, 1000):
        for y in range (1, 1000):
            for z in range(1, 1000):
                if x*x == y*y + z*z:
                    print y, z, x
                    print '-'*50

if __name__ == '__main__':
    main()

问题答案:

毕达哥拉斯三元组是宣称“ for 循环被认为是有害的”的一个很好的例子,因为for循环引诱我们思考计数,这通常是任务中最不相关的部分。

(我将坚持使用伪代码来避免语言偏见,并且为了简化伪代码,我不会优化egx * x和的多次计算y * y。)

版本1

for x in 1..N {
    for y in 1..N {
        for z in 1..N {
            if x * x + y * y == z * z then {
                // use x, y, z
            }
        }
    }
}

是最糟糕的解决方案。它生成重复项,并遍历空间中无用的部分(例如,每当时z < y)。它的时间复杂度是三次N

第2版 是第一个改进,来自要求x < y < z保留,例如:

for x in 1..N {
    for y in x+1..N {
        for z in y+1..N {
            if x * x + y * y == z * z then {
                // use x, y, z
            }
        }
    }
}

这样可以减少运行时间并消除重复的解决方案。但是,它仍然是三次方N。改进只是降低了N立方系数。

继续检查zafterz * z < x * x + y * y不再增加的值是没有意义的。这个事实激发了 Version 3的发展
,这是远离暴力迭代的第一步z

for x in 1..N {
    for y in x+1..N {
        z = y + 1
        while z * z < x * x + y * y {
            z = z + 1
        }
        if z * z == x * x + y * y and z <= N then {
            // use x, y, z
        }
    }
}

对于N1000,这是约比第2版快5倍,但它 仍然 对立方N

下一个见解是,x并且y是唯一的独立变量。z取决于它们的值,并且的上一个z值考虑的最后一个值是的下一个值的y良好 起始
搜索值y。这导致了 版本4

for x in 1..N {
    y = x+1
    z = y+1
    while z <= N {
        while z * z < x * x + y * y {
            z = z + 1
        }
        if z * z == x * x + y * y and z <= N then {
            // use x, y, z
        }
        y = y + 1
    }
}

这允许yz“扫动”上述值x一次。它不仅N以1000N的速度提高了100倍以上,而且在上是平方的,所以速度随增长而N增加。

我经常遇到这种改进,以至于除了最琐碎的用途(例如遍历数组)以外,对“计数循环”都不信任。

更新: 显然我应该指出一些有关V4的事情,这些事情很容易忽略。

  1. 两者 的的while圈由的值控制z(一个直接,其他间接地通过的平方z)。内部while实际上是在加速外部while,而不是与外部正交。 重要的是要查看循环的作用,而不仅仅是计算有多少个循环。

  2. V4中的所有计算都是严格的整数算术运算。通过比较,与浮点数之间的转换以及浮点数的计算成本很高。

  3. V4在恒定内存中运行,仅需要三个整数变量。没有要分配和初始化(并且可能导致内存不足错误)的数组或哈希表。

  4. 原来的问题让所有的xy以及x改变在相同范围内。V1..V4遵循该模式

下面是一组不太科学的计时(在我的较旧笔记本电脑上使用Eclipse下的Java在运行其他东西的情况下…),其中“使用x,y,z”是通过实例化具有三个值的Triple对象来实现的并将其放在ArrayList中。(对于这些运行,将N其设置为10,000,在每种情况下产生12,471个三元组。)

Version 4:           46 sec.
using square root:  134 sec.
array and map:      400 sec.

“数组和地图”算法 本质上是

squares = array of i*i for i in 1 .. N
roots = map of i*i -> i for i in 1 .. N
for x in 1 .. N
    for y in x+1 .. N
        z = roots[squares[x] + squares[y]]
        if z exists use x, y, z

“使用平方根”算法 本质上是

for x in 1 .. N
    for y in x+1 .. N
        z = (int) sqrt(x * x + y * y)
        if z * z == x * x + y * y then use x, y, z

V4的实际代码是:

public Collection<Triple> byBetterWhileLoop() {
    Collection<Triple> result = new ArrayList<Triple>(limit);
    for (int x = 1; x < limit; ++x) {
        int xx = x * x;
        int y = x + 1;
        int z = y + 1;
        while (z <= limit) {
            int zz = xx + y * y;
            while (z * z < zz) {++z;}
            if (z * z == zz && z <= limit) {
                result.add(new Triple(x, y, z));
            }
            ++y;
        }
    }
    return result;
}

注意,这x * x 在外部循环中计算的(尽管我没有去缓存z * z);在其他变体中进行了类似的优化。

我会很高兴按要求提供Java源代码,以提供我选择的其他版本,以防万一我没有正确实现任何东西。



 类似资料:
  • 勾股OA办公系统是一款简单实用的开源免费的企业办公系统。系统集成了系统设置、人事管理模块、消息管理模块、企业公告、知识库、审批流程设置、办公审批、日常办公、财务管理、客户管理、合同管理、项目管理、任务管理等模块。系统简约,易于功能扩展,方便二次开发。 内置模块 配置管理:对系统的常规配置信息进行维护,网站配置管理功能统一维护。 用户管理:维护管理系统的用户,常规信息的维护与账号设置。 菜单管理:配

  • 勾股CMS是一套基于ThinkPHP6 + Layui + MySql打造的轻量级的通用后台管理框架。系统后台集成了主流的通用功能,如:登录验证、系统配置、操作日志管理、角色权限管理、功能管理(后台菜单管理)、导航设置、网站地图、轮播广告、TAG关键字管理、搜索关键字管理、文件上传、数据备份/还原、文章功能、商品功能、单页面管理、用户管理、用户操作日志、用户注册/登录、 API接口等。更多的个性化

  • 勾股 DEV 是一款专为IT研发团队打造的项目管理与团队协作的系统工具,可以在线管理团队的工作、项目和任务,覆盖从需求提出到研发完成上线整个过程的项目协作。 通过“项目(Project)”的形式把成员、需求、任务、缺陷(BUG)、文档、互动讨论以及各种形式的资源组织在一起,团队成员参与更新任务、文档等内容来推动项目的进度,同时系统利用时间线索和各种动态的报表的形式来自动给成员汇报项目进度。 系统特

  • 问题内容: tl; dr Python是否会重用ID?生命周期不重叠的两个对象获得相同ID的可能性有多大? 背景: 我一直在从事一个纯粹用Python 3编写的复杂项目。我一直在测试中看到一些问题,并花了大量时间寻找根本原因。经过一些分析,我怀疑当测试整体运行时(由专门的调度员精心策划并运行),它正在重用某些模拟方法,而不是用其原始方法实例化新对象。为了检查解释器是否正在重用,我使用。 问题: 通

  • 所以我试图写一个程序,循环通过三角形的三个边的所有可能的边长组合,并打印遵循勾股定理的那些(即,侧A(sqr)侧B(sqr)=斜边(sqr))。匹配的,它应该打印。然而,数学没有按照它应该的方式执行。我认为问题在于我如何设置我的循环。 那么我的问题是,我应该如何设置?因为我觉得for循环的执行方式如下: 最外层的循环将检查毕达哥拉斯条件是否满足。如果是,它将打印结果、递增并再次测试。当条件不满足时

  • 给定一个由n个整数组成的数组nums和一个目标,求出满足nums[i]+nums[j]+nums[k] 例如,给定nums=[-2,0,1,3],target=2。 返回2。因为有两个和小于2的三胞胎: