Java程序占用了太多内存

时间:2013-02-27 13:04:26

标签: java performance algorithm heap-memory

这是我制作程序的问题

  阿里巴巴在四十个小偷身上做了一招,并且能够抓住他们   在一个大洞穴里面,它是野狼的家。小偷是   没有任何武器,只有盗贼的长官才有刀。没有   武器他们将无法与狼战斗,所以他们决定   自杀而不是被活活吃掉。

     

他们都决定他们会站成一个圆圈而他们每三分之一   人会杀了自己,但盗贼的首领不喜欢   这个想法并没有打算自杀。他计算在哪里   他应该站起来,以便他是最后一个离开的人。

     

HackerMan希望基于这个故事构建游戏,而不是   杀死他决定参与者将离开游戏,并且   而不是每个第3个位置,它将是每个第2个位置。当然   在这场比赛中,参赛人数将远远超过40人。

     

输入

     

第一行输入是整数N(1 <= N <= 1000)   指定测试用例的数量。之后每行包含一个   整数X(5 <= X <= 100000000),它是参与者的数量   游戏。

     

输出

     

对于每个测试用例,生成一个包含该位置的行   幸存的参与者。假设参与者有序列号   数字从1到n并且计数从人1开始,即,   第一个离开的人是2号人。

     

示例输入

     

3 5 11 45

     

示例输出

     

3 7 27

这是我的解决方案程序

class SurvivalStrategy {

    public int next;
    public int value;
    public boolean alive;

    SurvivalStrategy(int n, int v)
    {
        this.next = n;
        this.value = v;
        this.alive = true;
    }

    public int getNext(){
        return this.next;
    }
    public void kill(){
        this.alive = false;
    }

    public void changeNext(int n){
        this.next = n;
    }


    public static void main(String[] args) throws IOException {

        System.out.println("Enter the number of cases");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = br.readLine();
        int N = Integer.parseInt(line);
        int[] array = new int[N];
        for(int a = 0; a < N; a++)
        {
            System.out.println("Enter No. of theives in case " + (a + 1));
            array[a] = Integer.parseInt(br.readLine());
        }
        for(int b = 0; b < N; b++)
        {
            try{

                int theives = 0;
                theives = array[b];
                SurvivalStrategy[] people = new SurvivalStrategy[theives];
                int i = 0;
                int nextctr = 2;
                for(i = 0; i < people.length; i++)
                {
                    people[i] = new SurvivalStrategy(nextctr, i + 1);

                    if(nextctr > people.length)
                    {
                        people[i] = new SurvivalStrategy(1, i + 1);
                    }
                    nextctr++;
                }

                int k = 0;
                int nextguy = 0;
                int survivers = people.length;
                boolean CarryOnJatta = true;
                int lastSurviver = 0;
                while(CarryOnJatta)
                {
                    if(k >= people.length)
                    {
                        k = 0;
                        k = k + 2;
                    }
                    if(people[k].alive)
                    {
                        //System.out.println(people[k].value + " is Alive");
                        nextguy = people[k].getNext();
                        if(people[nextguy - 1].alive)
                        {
                            people[nextguy - 1].kill();

                            people[k].changeNext(people[nextguy - 1].next);
                            lastSurviver = people[k].value;
                            survivers--;
                        }else{
                            k = k + 2;
                        }
                        k = k + 2;
                    }else{
                        k = k + 2;
                    }

                    if (survivers == 1)
                    {
                        CarryOnJatta = false;
                        System.out.println("" + lastSurviver);

                    }
                }




            } catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

我的程序为小值提供输出,但不为大值输出。 如果我尝试输入(23987443)我得到Java堆大小超过错误。 有什么方法可以改善这个节目的空间和时间复杂性。 如果他们正在生成所需的输出,我也可以使用其他算法。

3 个答案:

答案 0 :(得分:3)

你在堆上分配至少23987443 * sizeof(SurvivalStrategy)内存 - 每个案例大约300MB,这只是在这行代码之前:

SurvivalStrategy[] people = new SurvivalStrategy[theives];

我想挑战的目的是教你高效的内存处理 - 所以不要一次分配整个内存,而是需要逐个处理你的项目,这样你一次只能分配几个项目,让GC收集不再需要的那些。

答案 1 :(得分:0)

您可以尝试为JVM分配更多内存,最近有一篇关于此的帖子: Java Heap Space error from command line

答案 2 :(得分:0)

你可以使用循环LinkedList。将节点添加到列表中,并使用计数算法遍历列表。每当有人输了,只需在该人身上调用一个删除,这将标记它有资格进行垃圾收集(假设该列表包含您节点的唯一引用)。

更好的是,无需在列表的第一个周期中一次性添加所有人。如果它们是V迭代的倍数,您就不能添加某人。这应该会大大减少你的内存使用量。

这将节省堆上的空间,因为您维护的最大大小为N,但会有更多的分配/释放开销。仍然,linkedList.remove提供O(1)复杂性。我认为它会清理你的代码并使其更容易理解