题目描述

给出一个正整数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;
    }
}

总结

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

Logo

昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链

更多推荐