8-连续非负整数

题目描述

给出一个正整数N和长度L,找出一段长度大于等于L的连续非负整数,他们的和恰好为N。答案可能有多个,我们需要找出长度最小的那个。
例如 N = 18 L = 2:
5 + 6 + 7 = 18
3 + 4 + 5 + 6 = 18
都是满足要求的,但是我们输出更短的 5 6 7 。

Me

主要使用了队列的思想,绕了一大圈还运行超时……

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int a = in.nextInt();
        int b = in.nextInt();
        printList(a, b);
    }

    public static int printList(int N, int L) {
        int pivot=(N+1)/2, sum=pivot, len=1;
        Node begin=new Node(pivot), now=begin, t;
        // 逆序确保获得最短的连续非负整数(从中值开始)
        for (int i=pivot-1; i>=0; i--) {
            t = new Node(i);
            now.next = t;
            // prior指针确保输出时正序
            t.prior = now;
            sum += i;
            len ++;
            if (sum == N && len >= L) {
                if (len <= 100) {
                    t.printValues();
                    return 0;
                }
                System.out.println("No");
                return 0;
            } else if ((sum > N || sum == N) && i!=1) {
                sum -= begin.value;
                begin = begin.next;
                begin.prior = null;
                len --;
            }
            now = now.next;
        }
        System.out.println("No");
        return 0;
    }
}

class Node {
    Node prior;
    Node next;
    int value;
    public Node(int value) {
        this.value = value;
    }
    public Node() {
    }
    public void printValues() {
        Node p = this;
        while (true) {
            System.out.print(p.value);
            p = p.prior;
            if (p != null) {
                System.out.print(" ");
            } else {
                break;
            }
        }
    }
}

此思路的主要缺陷:

  • printValues方法中需要再次扫描队列,并且没啥好的方法可以避免该冗余;
  • 主循环for (int i=pivot-1; i>=0; i–) 除非中途遇到(sum == N && len >= L),否则必须从头扫到尾,当输入的N很大且无连续非负整数组合时,耗时长。

总之,这是一个很笨还有点暴力的方法……

等差数列

只要!把这道题看作求解等差数列!一个至多(L-100)的循环就可以解决这个问题。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int a = in.nextInt();
        int b = in.nextInt();
        display(a, b);
    }
    public static int display(int N,int L) {
        for (int c=L; c<101; c++) {
            if (2*N%c == 0 && (2*N/c-c+1)%2 == 0) {
                int a = (2*N/c-c+1)/2;
                for (int j=0; j<c; j++) {
                    System.out.print(j+a);
                    if (j < c-1) System.out.print(" ");
                }
                return 0;
            }
        }
        System.out.print("No");
        return 0;
    }
}

总结

做题的时候除了用好各种工具(栈、队列、树……),最重要的是动脑子,从算法角度得到突破。思考比工具更重要,也更有效。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值