算法学习:简单起步

如何学习算法,目前我也是一点一滴的积累。从大学时接触到算法,到毕业这么多年,回想起来似乎对于算法的了解还仅仅只是概念。现在对于如何学习,我想不应该仅仅是哪一本算法的书翻翻看那么简单,至少要知道算法是为了解决问题而存在,不能只是把代码背下来,或者把书翻完就算学完。
现在我的学习就是从简单开始,记录下来,也是希望给自己一个鞭策。下面进入今天的正题。

先从简单题开始

有n根棍子,棍子的i长度为ai。想要从中取出三根棍子组成周长尽可能长的三角形。请输出最大的周长,若无法组成三角形则输出0。
选择3根棍子,它们能组成三角形的充要条件为最长棍子的长度 < 其余两根棍子的长度之和。

一、O(n3)

首先想到的应该是三角形的定义:两边之和要大于最长的边。否则就成不了三角形。
两边之和要大于最长的边。否则就成不了三角形。
于是可以想到一种算法,首先三重循环枚举所有方案,再根据三角形的定义判断是否能组成三角形。如果可以,就是备选答案。
因为用了三重循环,所以复杂度是O(n3)。

    /**
     * 最大周长1 O(n3)
     * 
     * @param a
     * @return
     */
    private static int triangle1(int[] a) {
        int answer = 0;
        //循环数组,第二、三次循环从没选的里去就好
        for (int i = 0; i < a.length; i++) {
            for (int j = i + 1; j < a.length; j++) {
                for (int k = j + 1; k < a.length; k++) {
                    //取得三数之和,有可能就是要求的周长
                    int perimeter = a[i] + a[j] + a[k];
                    //取得三数中最大的数
                    int max = getMax(new int[] { a[i], a[j], a[k] });
                    //取得其余两数之和
                    int rest = perimeter - max;
                    //如果最大边小于其余两边之和,则可以组成三角形
                    if (max < rest) {
                        //更新答案
                        answer = getMax(new int[] { perimeter, answer });
                    }
                }
            }
        }
        return answer;
    }

二、O(nlogn)

学习算法是一个需要不断思考的过程。
上面的算法虽然能解决问题,但是是否有效率更好的算法呢?
如果将输入排序,然后依次选择相邻的三个,这样只需要一次循环了。
排序时间:O(nlogn)
循环时间:O(n)
所以时间复杂度应该就是O(nlogn)。

    /**
     * 最大周长2 O(nlogn)
     * 
     * @param a
     * @return
     */
    private static int triangle2(int[] a) {
        int answer = 0;
        //排序
        Arrays.sort(a);
        //遍历
        for (int i = 0; i < a.length; i++) {
            if (i + 2 < a.length) {
                //取得前两数之和
                int temp = a[i] + a[i + 1];
                // 如果第三个数小于两数之和,则可以为三角形
                if (a[i + 2] < temp) {
                    //更新答案,且最后一次的答案肯定是周长最大
                    answer = temp + a[i + 2];
                }
            }
        }

        return answer;
    }

最后

算法我也算重新开始学习,在学习过程中难免会有理解不足和不正确的地方。希望大家看到后指正,我也会积极改正更新,以免误导他人。

参考代码:参考代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值