2013-02-27 129 views
0

这是我的问题,为此,我制作的节目Java程序占用太多的内存

阿里巴巴做了四十大盗一招,并能够捕获它们 一个大山洞这是内家野狼。盗贼是没有任何武器的 ,只有盗贼的首领有刀。没有 武器,他们将无法与狼战斗,所以他们决定自杀而不是被活着吃掉。

他们都认为他们会站成一个圈,他们每三个人就会自杀,但盗贼队长不喜欢 这个想法,并没有杀死自己的意图。他计算他应该站在哪里,以便他是最后一位。

HackerMan想根据这个故事建立一个游戏,但不是 杀害,他决定参与者将离开游戏,而不是每第三个位置,它将在每个第二个位置。当然 在这场比赛中参加者的人数将远远超过40人。

输入

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

输出

对于每组数据生成包含 参与者谁生存的位置的线。假设参与者具有序​​列 号从1到n,并且计数与人1,即开始, 第一人的离去是具有数2.

采样输入

样本输出

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堆大小超过错误。 有什么办法可以改善这个程序的空间和时间复杂性。 我也打开其他算法,如果他们正在产生所需的输出。

+0

我正在解决一个编码挑战,这是给出的问题,我写了这个完整的代码来解决问题,但我的程序正在占用太多的内存和时间来返回所需的结果 – 2013-02-27 13:09:34

+1

问题听起来类似于[this](http://en.wikipedia.org/wiki/Josephus_problem)。 – Dukeling 2013-02-27 13:16:40

+0

@Dukeling:没错,在那个页面上有一个公式可以立即给出正确的答案。 – Groo 2013-02-27 14:17:33

回答

0

你可以尝试分配更多的内存给JVM,还有最近的文章中有关此: Java Heap Space error from command line

+0

如果我只有256 MB内存来执行程序,该怎么办?我看到有几个人已经完成了这些工作,他们的代码正常工作,所以这就是为什么我很想知道我哪里出了问题。因为我的算法似乎工作得很好,它可能不是最有效的一个 – 2013-02-27 13:11:12

+0

@Ishan如果你只有256MB,则不能分配更多,在这种情况下,23987443 SurvivalStrategy对象似乎大约为256MB。你必须通过消耗更少的内存来提高你的实现效率,没有任何'技巧'来解决编码挑战门户上的内存重构问题。 – us2012 2013-02-27 13:55:23

3

您分配至少23987443 *的sizeof在堆(SurvivalStrategy)内存 - 这将是围绕每300MB单一的情况下,这是唯一的这行代码之前:

SurvivalStrategy[] people = new SurvivalStrategy[theives]; 

我猜的挑战是设计与有效的内存处理的优点,教你 - 所以不是一次分配整个内存,你需要处理你的物品一个接一个,这样你就只能分配一些物品我让这些不再需要的人被GC收集。

+0

2398744本身就是盗贼的数量,所以正在使用的内存是 23987443 * sizeof(SurvivalStrategy) – 2013-02-27 13:39:20

+0

我站得更正了,但只有在重新进入基于int b的循环之前,这才是真实的。尝试在探测器下运行4个23987443小偷 - 您会看到堆迅速增长到1.2GB(取决于您的机器和GC)。 – 2013-02-28 10:01:39

0

你可以使用循环LinkedList。将您的节点添加到列表中,并使用计数算法遍历列表。每次有人丢失时,只需调用该人员的删除,这将标记为有资格进行垃圾回收(假设该列表仅包含对您的节点的唯一引用)。

更好的是,不需要在列表的第一个循环中一次添加所有人。如果他们是V迭代的倍数,你可以不加人。这应该会让你的内存使用量增加很多。

这会节省堆上的空间,因为你保持的最大尺寸是N,但会有更多的分配/释放开销。不过,linkedList.remove提供了O(1)的复杂性。我认为它会清理你的代码并且使它更容易理解