簡體   English   中英

Java IndexOutOfBounds 嘗試獲取列表中的上一個條目時

[英]Java IndexOutOfBounds when trying to get a previous entry in a List

我正在研究一個問題,您應該返回給定的 n 行 pascals 三角形和 int n 並將其作為列表列表返回。 但是,當我嘗試調用前一行時,我得到了一個索引越界異常,我不確定為什么。

public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> triangle = new ArrayList<List<Integer>>();
        List<Integer> row = new ArrayList<>();
        for(int i = 0; i < numRows; i++){
            for(int j = 0; j <= i; j++){
                if(j == 0 || j == i){
                    row.add(1);
                }
                else{
                    if(i != 0 && j != 0){
                        int num = triangle.get(i-1).get(j-1) + triangle.get(i-1).get(j);
                        row.add(num);
                    }
                }
            }
            triangle.add(row);
            row.clear();
        }
        return triangle;
    }

我添加了if(i != 0 && j != 0)行,希望能解決它,但錯誤仍然存在。

計算正在執行的new語句的數量。

我只計算了 2 個新語句,都在你的循環開始之前。

這意味着有 2 個數組列表。 總計

鑒於您的代碼應該返回比這更多的列表,這是如何工作的? 好吧,java是基於引用的。 事實上,所有非原始值都是引用 它就像地址簿中的一頁,而不是房子。 List<Integer> row = new ArrayList<>(); 做兩件事:

  • 它建造了一座房子(這是new ArrayList<>();部分)
  • 它在標題為“行”的頁面上寫下了這所房子的地址。
  • triangle.add(row)只會創建地址簿頁面的副本,而不是房屋的副本。 您只需記下地址,然后走到房子里,砸碎里面的所有東西( row.clear() ),然后重新開始。 你一直在給同一個房子加油,把里面的一切都砸碎。 triangle是一本包含很多頁的地址簿,每一頁都有相同的地址,所有的地址都通向一所房子,有人反復填滿它,把它砸得粉碎。

這讓我們回到:計算new.

在這里,您預計一個 5 行的 sierpinski 總共有 6 個列表:每行 1 個列表,然后還有一個列表列表。 這意味着我需要執行 6 個“新”語句。

您需要刪除row.clear() 您正在清除剛剛添加到三角形的行的內容。 您這樣做的原因是您認為可以繼續向三角形添加同一行; 您需要為每個循環創建一個新行。

您在為row使用/重復使用 List 的方式上犯了一個錯誤。

您必須為每個新行創建一個全新的列表,否則,您將在 trangle 的每一行中放置相同的實例,並且在每一行中添加完全相同的數字。

你所做的產生了一個像這樣的“三角形”:

1

11
11

第三行必須從第二行獲取值,但它失敗了,因為您在計算第三行之前清除了該行(因此同時清除了每一行)。

需要進行以下更改:

public List<List<Integer>> generate(int numRows) {
  List<List<Integer>> triangle = new ArrayList<List<Integer>>();

  for(int i = 0; i < numRows; i++){
    List<Integer> row = new ArrayList<>();  // <<-- new row instead of clearing it

    ...
  }

  trangle.add(row);
  // row.clear(); // <-- this was the second part of the mistake

我看到你的代碼有問題。 問題是您試圖在將元素添加到三角形列表之前訪問 Pascal 三角形的前一行中的元素。 換句話說,當 i 為 0 時,您試圖在外循環的同一迭代中訪問 triangle.get(i-1) 。

解決此問題的一種方法是將生成三角形每一行的內部循環移動到一個單獨的函數中。 然后,您可以手動添加三角形的第一行並調用該函數生成后續行。 這將確保在您嘗試訪問之前的行之前已將它們添加到三角形列表中。

這是應該解決索引越界異常的修改代碼:

public List<List<Integer>> generate(int numRows) {
    List<List<Integer>> triangle = new ArrayList<List<Integer>>();
    if (numRows == 0) return triangle;

    // Add the first row manually
    triangle.add(Arrays.asList(1));

    // Generate the remaining rows
    for (int i = 1; i < numRows; i++) {
        List<Integer> row = new ArrayList<>();
        for (int j = 0; j <= i; j++) {
            if (j == 0 || j == i) {
                row.add(1);
            } else {
                int num = triangle.get(i-1).get(j-1) + triangle.get(i-1).get(j);
                row.add(num);
            }
        }
        triangle.add(row);
    }

    return triangle;
}

我希望這有幫助。 如果您有任何問題或需要進一步說明,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM