2016-10-16 69 views
0

我有一個整數數組。從第一個位置開始,我然後在給定索引處添加或減去值以在數組中移動。這個謎題的目的是到達數組的最後一個元素0。我知道這個問題已經在遞歸中解決了,但我應該給出一個非遞歸解決方案。 爲了避免無限循環,我提出一個條件Java拼圖在整數陣列中左右移動

if (a[index] == a[index+temp]) 

和代碼工作正常,當我傳遞一個數組是這樣的:

int a [] = { 3, 1, 2, 3, 0 }; 

但後來我通過int a [] = {3, 6, 4, 3, 3, 4, 3, 5, 3, 0 },它告訴我的拼圖沒有解決方案,這是不正確的。 這裏是我的代碼部分:

 int temp; 
     int index = 0; 

     while (index < (a.length-1) && index >= 0) 
      { 
       temp = a[index]; 

       if ((index+temp) <= a.length-1) 
       { 
        if (a[index] == a[index+temp]){ 
         solution = false; 
         break; 
        } 
        index = index + temp; 
       } 
       else if ((index-temp) >=0) 
       { 

        index = index - temp; 
       } 

     } 

我附上照片從我的任務這也解釋了算法的行爲。 enter image description here

+1

你能解釋一下在手的算法多一點?我真的不明白「右移」和「左移」實際上是如何發生的......(如:爲什麼在步驟2中「向右移動」停在1 ...?) – MordechayS

+0

他應該嘗試兩個方向我認爲,無論哪一個導致解決方案。 –

+0

@MordechayS當我在起始位置時,值是3.我只能向右移動三個位置。在位置a [3]處,值爲1,所以我可以向右或向左移動。 – q212

回答

1

你在這裏有什麼基本上是一個有向無權圖。每個索引都與1或2個其他索引連接。

現在,考慮到這一點,您可以使用「breadth first search」算法很容易地解決此問題,該算法工作得很好,無需遞歸。

這裏是相當冗長的實施例:https://ideone.com/yzeBzz

List<Integer> solve(int... a) { 
    //Value in each element is the index, from where we can come here 
    int[] path = new int[a.length]; 
    Arrays.fill(path, -1); //No index is accessible yet 

    //Queue of positions that were visited from somewhere, but nothing was tried to be 
    //visited from them. At the beginning, 0 is in the list, because it's starting point. 
    //Then, if we visit index 3, it is added to this list for later processing. 
    Queue<Integer> posQueue = new LinkedList<>(); 
    posQueue.add(0); 
    path[0] = 0; //0 index is accessible from itself, this is starting position 

    while (!posQueue.isEmpty()) { 
     int pos = posQueue.remove(); 
     int prPos = pos - a[pos]; 
     int nxPos = pos + a[pos]; 
     if (prPos >= 0 && path[prPos] == -1) { 
      path[prPos] = pos; 
      posQueue.add(prPos); 
     } 
     if (nxPos < a.length && path[nxPos] == -1) { 
      path[nxPos] = pos; 
      posQueue.add(nxPos); 
     } 

     if (path[a.length-1] != -1) { 
      break; 
     } 
    } 

    if (path[a.length-1] == -1) { 
     return null; 
    } 

    //Collect the path 
    List<Integer> result = new ArrayList<>(); 
    int idx = a.length-1; 
    while (idx != 0) { 
     result.add(0, idx); 
     idx = path[idx]; 
    } 
    result.add(0, 0); 
    return result; 
} 

正如任何廣度搜索算法中,複雜度爲O(N)。

+0

我認爲我贏了2秒... :) – ajb

+0

嗯,我有一個維基百科鏈接那裏的獎勵積分;) – bezmax

+0

是的,它會花費我超過2秒鐘來找到該鏈接並添加它。 – ajb

-1

這可能會實現:

boolean solve(int... a) { 
    for (int i = 0; i < 1 << a.length; i++) { 
     int pos = 0; 
     for (int j = 0; j < 32; j++) { 
      if ((i & (1 << j)) == 0) { 
       if ((pos -= a[pos]) < 0) { 
        break; 
       } 
      } else { 
       if ((pos += a[pos]) >= a.length) { 
        break; 
       } 
      } 
      if (a[pos] == 0) { 
       return true; 
      } 
     } 
    } 
    return false; 
} 
+0

謝謝,shmosel! – q212

+0

@shmosel這基本上是一些蠻力的巫術巫術。你可以使用一個數組而不是位掩碼獲得更清晰的代碼和相同的可怕O(2^n)複雜性。例如,嘗試用30個整數運行它。 – bezmax