2016-09-30 10 views
1

Я пытаюсь задать стандартный вопрос для интервью, который должен добавить две цифры в виде связанных списков и вернуть добавленный ответ. Возникает вопрос:Невозможно назначить главный узел LinkedList в Java для дальнейшего использования

Вам даются два связанных списка, представляющих два неотрицательных числа. Цифры хранятся в обратном порядке, и каждый из их узлов содержит на одну цифру. Добавьте два числа и верните их как связанный список.

Входной сигнал: (2 -> 4 -> 3) + (5 -> 6 -> 4) Выход: 7 -> 0 -> 8

342 + 465 = 807 Make sure there are no trailing zeros in the output list So, 7 -> 0 -> 8 -> 0 is not a valid response even though 

значение по-прежнему 807.

Теперь код, который я пишу, принимает два аргумента в виде ListNode типов данных, который является исходным узлом LinkedLists. Что я не понимаю -

  1. Как сохранить головной узел списка для ссылки позже?
  2. Как вызов по значению и вызов по ссылке в Java? Я имел дело с указателями и звонил по ссылке в C++, но сейчас я пробовал вещи на Java, и это совсем другое.

    class ListNode { 
        public int val; 
        public ListNode next; 
        ListNode(int x) { 
         val = x; 
         next = null; 
        } 
    } 
    
    
    public class Solution { 
    
        public ListNode reverse(ListNode head) { 
         ListNode curr = head; 
         ListNode next = null; 
         ListNode prev = null; 
         while (curr != null) { 
          next = curr.next; 
          curr.next = prev; 
          prev = curr; 
          curr = next; 
         } 
         head = prev; 
         return head; 
        } 
    
    
        public ListNode addTwoNumbers(ListNode a, ListNode b) { 
         ListNode node = null; 
         ListNode head = null; 
         boolean carry = false; 
         while (a != null || b != null) { 
          int f = 0, s = 0; 
          if (carry) { 
           f++; 
          } 
          carry = false; 
          if (a != null) { 
           f += a.val; 
           a = a.next; 
          } 
          if (b != null) { 
           s = b.val; 
           b = b.next; 
          } 
          if (f + s > 9) { 
           carry = true; 
          } 
          int curr = (f + s) % 10; 
          node = new ListNode(curr); 
          if (head == null) { 
           head = node; 
          } 
          node = node.next; //warning that 'value of node assigned is never used' 
         } 
         if (carry) { 
          node = new ListNode(1); 
         } 
         printList(head); 
         return node; 
        } 
    } 
    
+0

«Как позвонить по значению и вызов по справочным в Java» Ява [вызов по значению] (http://stackoverflow.com/questions/40480/is-java-pass-by- reference-or-pass-by-value) всегда. Но то, что понимается под «значением» в этом контексте, запутывает: значение передаваемой переменной, которое может быть ссылкой. Таким образом, пока ссылочный объект не передается по значению, переменная, относящаяся к этому объекту; это означает, что вы не можете делать такие вещи, как обмен значениями в отдельном методе, как на C++. –

+0

@AndyTurner Что было бы лучшим способом решения таких вопросов LinkedList, как это в Java?Поддержание головы и других ценностей в боль, потому что в Java, если я просто делаю 'head = node', тогда значение головы изменяется в соответствии с узлом, и я не могу получить начальное значение в конце. Как этого избежать? – tsaebeht

ответ

1

node играет неоднозначную роль.

 node = new ListNode(curr); 
     node = node.next; // assigns null 

Переименовать node в previous и сделать:

 int curr = (f + s) % 10; 
     ListNode newNode = new ListNode(curr); 
     if (head == null) { // Or `previous == null` 
      head = newNode; 
     } else { 
      previous.next = newNode; 
     } 
     previous = newNode; 

    ... 
    return head; 

Методика для обработки head, чтобы сделать его частное поле контейнерного класса LinkedList.

Как и в java, передача параметров является позывным: f(a) никогда не изменяет переменную a: слот, в котором хранится указатель/значение объекта. Вместо этого объект-указатель/значение помещается в стек. (Значение объекта может иметь свои поля.)

Таким образом, рекурсивная вставка может выглядеть как head = insert(head, ...).

В C можно использовать на ступенчатость, а не только для передачи параметров:

ListNode* head = NULL; 
ListNode** node = &head; 
shile (...) { 
    ... 
    *node = newNode; 
    node = &(newNode->next); 
} 
+0

'Техника обработки головы - сделать это частным полем класса контейнера LinkedList' Именно это и есть мысль. Предыдущий метод кажется хорошим обходным решением этой проблемы, спасибо – tsaebeht

+0

Ваш ответ не подходит мне. Если я напечатаю значения 'head' и previous на каждом этапе, я получаю тот же ответ. Посмотрите на код здесь: http: //ideone.com/N7dvLX – tsaebeht

+0

Пожалуйста, отредактируйте свой ответ. Это будет 'int curr = (f + s)% 10; ListNode newNode = новый ListNode (curr); if (previous == null) { previous = newNode; head = newNode; } else { previous.next = newNode; previous = previous.next; } ' – tsaebeht

0

Почему так сложно?

public class Solution { 

    public ListNode addTwoNumbers(ListNode a, ListNode b) { 
     int firstNumber = nodeToNumber(a); 
     int secondNumber = nodeToNumber(b); 
     return numberToNode(firstNumber + secondNumber); 
    } 

    public int nodeToNumber(ListNode node) { 
     if (node.next != null) return node.value + 10 * nodeToNumber(node.next); 
     return node.value; 
    } 

    public ListNode numberToNode(int number) { 
     ListNode result = new ListNode(number % 10); 
     if (number > 10) result.next = numberToNode(number/10); 
     return result; 
    } 
} 
Смежные вопросы