JAVA编程练习—第一题

题目:输入一个正数n,输出所有和为n连续正数序列。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8

最简单,也是最笨的方法,就是两次循环,代码如下:

public void getSeri(int n) {
    if (n == 1) {
        return;
    }
    //防止溢出
    int length = (n+1) >>> 1;
    int sum = 0;
    for (int i = 1; i < length; i++) {
        sum = i;
        for (int j = i +1; j <= length; j++) {
            sum += j;
            if (sum == n) {
                System.out.println(i + "-" + j);
                break;
            } else if (sum > n) {
                break;
            }
        }
    }
}

我们先看,这段代码,首先如果输入的是 1直接返回,因为不会有连续的值相加等于自己。然后看length,这个值是我们for循环的最大值,因为,length的值是输入值的中间值,一单超过了中间值,任意两个值相加都会比n大。比如说,15的中间值是8,8+9=17>15,之后的所有序列都大于15了,所以循环到8就可以终止了,节省下效率。

虽然我们在循环上稍微注意了下效率,但实际上,这个代码的效率还是很低了,因为做了两次嵌套循环。如果n=100的话,就要做50*50=2500次循环,n越大,速度越慢。

所以我又想了,第二种方法,代码如下:

public void getSeriProv(int n) {
        if (n == 1) {
            return;
        }
        int length = (n+1) >>> 1;
        List queue = new LinkedList<>();
        int sum = 0;
        for (int i =1; i <= length; i++) { 
            queue.add(i); 
            sum += i; 

            while (sum > n) {
                int oldvalue = queue.remove(0);
                sum -= oldvalue;
            }

            if (sum == n) {
                System.out.println(queue.get(0) + "-" + queue.get(queue.size()-1));
                int oldvalue = queue.remove(0);
                sum -= oldvalue;
            }
        }
    }

我先创建了一个队列。每次循环都向队列的列尾加入当前的数值,同时计算sum和,如果sum比n大的话就移除列头的值,直到sum<=n,如果sum=n则,直接打印结果,移除列头,进行下一次的循环。

因为是连续数值的和,这样我就不用每次都从头sum,只需要每次sum队列里面的值即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容