2015-07-24 3 views
0

Целью кода является поиск номеров, которые составляют targetNumber. Например, если targetNumber = 9, тогда код должен получить первые два появляющихся индекса чисел, которые добавляются до targetNumber. Когда я запускаю свой код, вывод выглядит следующим образом:Неверное вычисление внутри вложенных циклов

The indexes are 10 and 1 

Что не так с логикой кода? Заранее спасибо!

public class TwoSum { 

    public static void main(String[] args){ 

     int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3}; 
     int targetNumber = 9; 
     int index1 = 0;; 
     int index2 = 0; 

     for(int i = 0; i < myArray.length; i++){ 
      for(int j = 1; j < myArray.length; j++){ 
       if(myArray[i] + myArray[j] == targetNumber){ 
        index1 = i; 
        index2 = j; 
        break; 
       } 
      } 
     } 
     System.out.println("The indexes are " + index1 + " and " + index2); 
    } 
} 
+0

Просто чтобы прояснить, вы ждете выхода, чтобы быть '1' и' 7'? – user2718281

+0

Поскольку индекс основан на нуле, индексы 10 и 1 ссылаются на последний «3» (индекс 10) и первый «6» (индекс 1). Это далеко не изящное решение, но они складываются до «9». Так в чем проблема, в которой вам нужна помощь? Что он не использует первое вхождение «3» (т. Е. Индекс 7)? – Carsten

+0

@ user2341963, '0' (1) и' 8' (7). Я должен печатать только индексы чисел. –

ответ

1

Я считаю, что вы ожидаете индексы 0 и 8 (значения 1 и 8). Проблема в том, что ваш оператор break ломается только от внутреннего цикла, а не от внешнего цикла. Вам нужно использовать флаг, чтобы знать, что вы также должны выйти из внешнего цикла. Также рассмотрите печать сообщения, если совпадение не найдено.

public static void main(String[] args) throws Exception { 
    int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3}; 
    int targetNumber = 9; 
    int index1 = 0; 
    int index2 = 0; 

    boolean stop = false; 
    for (int i = 0; i < myArray.length && !stop; i++) { 
     for (int j = i + 1; j < myArray.length && !stop; j++) { 
      if (myArray[i] + myArray[j] == targetNumber) { 
       stop = true; 
       index1 = i; 
       index2 = j; 
      } 
     } 
    } 
    System.out.println(stop 
      ? "The indexes are " + index1 + " and " + index2 
      : "No match found"); 
} 

Или просто распечатать результаты внутри внутреннего цикла и использовать return вместо break. Таким образом, вам не нужно использовать флаг.

public static void main(String[] args) throws Exception { 
    int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3}; 
    int targetNumber = 9; 

    for(int i = 0; i < myArray.length; i++){ 
     for(int j = i + 1; j < myArray.length; j++){ 
      if(myArray[i] + myArray[j] == targetNumber){ 
       System.out.println("The indexes are " + i + " and " + j); 
       return; 
      } 
     } 
    } 
    System.out.println("No match found"); 
} 

Результаты:

The indexes are 0 and 8 
+0

Отличный ответ, @ Shar1er80. Благодаря! –

4

При разрыве, вы нарушаете только из внутреннего цикла, так что вместо распечатки 1, а затем 10, внешний контур продолжается, завершение естественно, и в результате распечатки индекса 10 затем индекс 1 .

Интересный результат состоит в том, что ваш код по существу находит последние пары чисел, которые суммируются с targetNumber, а не с первого. Если вы сделали ставку для циклов, а не вверх, код должен выплюнуть правильные значения, хотя это было бы не очень эффективно ...

+0

Но как вырваться из обеих петель сразу же, когда индексы найдены? Я попытался «ломать» после внутреннего цикла, но показал «мертвый код», @Aderis –

+0

@ Джон проверить мой ответ о том, как правильно нарушить внешний контур. – Aivean

0

Оператор break разбивает внутренний цикл, но не внешний. Таким образом, ее получение последний результат 3 и 6 вместо 1 и 8.

более подходящим способом может быть:

bool found=false; 
    for(int i = 0; i < myArray.length; i++){ 
     if(!found){ 
      for(int j = 1; j < myArray.length; j++){ 
       if(myArray[i] + myArray[j] == targetNumber){ 
        index1 = i; index2 = j;    
        found=true; 
        break; 
} } }} 
0

Есть три вещи, которые не так с вашим кодом:

  1. Согласно спецификации, вы хотите, чтобы найти первое соответствие индексов, в то время как вы на самом деле находят последние. Это происходит потому, что break разбивает только внутренний цикл. Легкое исправление заключается в использовании метки (outer:). Хотя более чистый подход будет использовать выделенный метод для выполнения поиска и return первое совпадающее значение.

  2. Вы проверяете пары индексов дважды, а также проверяете пары одного и того же индекса. Идиоматический подход, исключающий эту избыточность, заключается в том, чтобы запустить вложенный цикл из текущего значения индекса внешнего цикла (j = i) или (j = i + 1), если вы не хотите иметь пары одного и того же индекса (i, i).

  3. Вы не рассматриваете ситуацию, когда соответствующий индекс не найден. В этом случае вы покажете, что результат (0,0) является результатом.

Вот ваш код исправлено:

 public static class TwoSum { 

      public static void main(String[] args) { 
       int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3}; 
       int targetNumber = 9; 
       int index1 = -1; 
       int index2 = -1; 

       outer: 
       for (int i = 0; i < myArray.length; i++) { 
        for (int j = i + 1; j < myArray.length; j++) { 
         if (myArray[i] + myArray[j] == targetNumber) { 
          index1 = i; 
          index2 = j; 
          break outer; 
         } 
        } 
       } 

       if (index1 >= 0) { 
        System.out.println("The indexes are " + index1 + " and " + index2 + "(Values " + myArray[index1] + 
          " and " + myArray[index2] + ")"); 
       } else { 
        System.out.println("Not found"); 
       } 
      } 
     } 
+0

Кстати, существует более эффективный подход к этой проблеме (O (n), без вложенного цикла). Я могу поделиться, если вы заинтересованы. – Aivean

1

Чтобы сделать код немного чище; то есть, полностью вызывая инструкцию break, вы должны ввести логическую переменную с именем found в ваши циклы. Таким образом, вы можете вырваться из обоих из них более интуитивно, если вы найдете свой первый матч.

boolean found = false; 
for(int i = 0; i < myArray.length && !found; i++){ 
    for(int j = 1; j < myArray.length && !found; j++){ 
     if(myArray[i] + myArray[j] == targetNumber){ 
      found = true; 
      index1 = i; 
      index2 = j; 
     } 
    } 
} 
System.out.println("The indexes are " + index1 + " and " + index2); 

Если вы когда-нибудь интересно, что другие пары чисел добавить к вашей цели, создать Pair<T> класс, который может хранить такую ​​информацию. Вы бы не вырвались из каких-либо петель, поскольку вы по сути дела выполняете все это.

class Pair<T> { 
    final T firstValue; 
    final T secondValue; 


    Pair(T firstValue, T secondValue) { 
     this.firstValue = firstValue; 
     this.secondValue = secondValue; 
    } 

    public T getFirstValue() { 
     return firstValue; 
    } 

    public T getSecondValue() { 
     return secondValue; 
    } 

    @Override 
    public String toString() { 
     return "{" + firstValue + ", " + secondValue + "}"; 
    } 
} 

// later in your code 


List<Pair<Integer>> pairs = new ArrayList<>(); 

for(int i = 0; i < myArray.length; i++){ 
    for(int j = 1; j < myArray.length; j++){ 
     if(myArray[i] + myArray[j] == targetNumber){ 
      pairs.add(new Pair<>(i, j)); 
     } 
    } 
} 
System.out.println("The indexes are " + pairs); 

Вышеприведенные распечатывает:

The indexes are [{0, 8}, {1, 7}, {1, 10}, {5, 7}, {5, 10}, {7, 1}, {7, 5}, {10, 1}, {10, 5}] 
+0

Превосходно !!! Мне это нравится! – Shar1er80

Смежные вопросы