2016-08-04 3 views
3

Я пытался решить проблему Partition List на LeetCode. Проблема заключается в сортировке связанного списка с узлом целевого списка, так что все узлы списка, имеющие меньшее значение, чем целевое, будут поступать до цели, тогда как их первоначальный относительный порядок остается неизменным.Зачем нарушать связь между двумя узлами списка при разбиении списка?

Я смог составить простой алгоритм и передать онлайн-судье, в основном создавая два указателя и используя их каждый, чтобы связать либо узлы < цели, либо >= цель при перемещении по списку.

public ListNode partition(ListNode head, int x) { 
    ListNode ptr = head; 
    ListNode small = new ListNode(0); 
    ListNode big = new ListNode(0); 
    ListNode dummy_1 = big; 
    ListNode dummy_2 = small; 
    int i = 1; 
    while (ptr != null) { 
     if (ptr.val < x) { 
      small.next = ptr; 
      small = small.next; 
     } else { 
      big.next = ptr; 
      big = big.next; 
     } 
     ListNode help = ptr.next; 
     ptr.next = null; 
     ptr = help; 
    } 
    small.next = dummy_1.next; 
    return dummy_2.next; 
} 

следующие коды разрывает связь между ptr и ptr.next, и переместить
ptr к первоначальному ptr.next.

ListNode help = ptr.next; 
ptr.next = null; 
ptr = help; 

То, что я не совсем понял, еще в том, что, почему этот шаг необходим, так как мы можем двигаться ptr его next и непосредственно обновить ссылку позже, используя small.next = ptr и big.next = ptr в то время как петли;

Однако, когда я просто использовал ptr = ptr.next вместо трех строк кода выше, онлайн-судья ответил с ошибкой Memory Limit Exceeded.

Я был бы очень признателен, если кто-нибудь сможет это объяснить. Что может вызвать ошибку ограничения памяти, поскольку, как представляется, уже избегается какой-либо циклический список?

+0

Вы пишете это на Java или C++? Ваш код C++, но ваш тег - Java – JavaHopper

+0

Однако эти 3 строки необходимы для восстановления памяти.Если вы просто продвигаете указатель, узлы не удаляются, а ptr указывает на следующий узел в цепочке – JavaHopper

+0

@JavaHopper Спасибо за ваш ответ! Код действительно в java, извините, если стиль кодирования смущает вас. Итак, я думаю, что алгоритм может работать, по методу? Это просто занимает лишнее пространство памяти? – GettingBetter

ответ

1

Как прокомментировал, просто установив big.next = нуль работает (я управлял этим с помощью NetBeans/Java).

static ListNode partition(ListNode head, int x) { 
    ListNode ptr = head; 
    ListNode small = new ListNode(0); 
    ListNode big = new ListNode(0); 
    ListNode dummy_1 = big; 
    ListNode dummy_2 = small; 
    while (ptr != null) { 
     if (ptr.val < x) { 
      small.next = ptr; 
      small = small.next; 
     } else { 
      big.next = ptr; 
      big = big.next; 
     } 
     ptr = ptr.next; 
    } 
    small.next = dummy_1.next; 
    big.next = null; 
    return dummy_2.next; 
} 
1

Объект не будет иметь права на сбор мусора, если на него указана хотя бы одна ссылка.Вы можете следить this пост, чтобы построить краткое понимание вокруг этой концепции

Вот что происходит в обоих случаях

Случай 1:

ptr = ptr.next 

Предположим Linked List находится в следующем состоянии в течение первых итерация

enter image description here

продвигается, но предыдущий узел, имеющий значение 7 по-прежнему ссылается head

enter image description here

ptr является передовой, но предыдущий узел, имеющий значение 1 по-прежнему ссылается его предыдущего узла

enter image description here

ptr продвигается, но предыдущий узел, имеющий значение 3 по-прежнему ссылается на его предыдущий узел

enter image description here

И это продолжается до конца цикла. Если список имеет очень большой размер, тогда память не восстанавливается. Как ваш судья сказал, это может привести к ошибке, как Memory Limit Exceeded

Случай 2:

ListNode help = ptr.next; 
    ptr.next = null; 
    ptr = help; 

Предположим, Связанный список находится в следующем состоянии во время первой итерации.

  • help указывает на следующий узел указываемые ptr
  • ptr является повторно ссылается, чтобы указать на help, на следующей стадии
  • Следовательно, узел ранее, на который указывает ptr (тот, который имел значение 7) имеет право на сбор мусора
  • И память исправлена ​​

enter image description here

  • help указывает на следующий узел указываемые ptr
  • ptr является повторно ссылается, чтобы указать на help, на следующей стадии
  • Следовательно, узел ранее, на который указывает ptr (один из которых имеет значение 1) имеет право на сбор мусора
  • И память регенерируется

enter image description here

  • help указывает на следующий узел, на который указывает ptr
  • ptr повторно ссылки, чтобы указать на help, в следующем шаге
  • Следовательно узел ранее указывал на ptr (тот, который имел значение 3) имеет право на Garbage Collection
  • И память регенерируется

enter image description here

  • help указывает на следующий узел, на который указывает ptr
  • ptr повторно ссылается, чтобы указать на help, в следующем step
  • Следовательно, узел, на который раньше указывал ptr (тот, который имел значение 2) имеет право на Garbage Collection
  • И память регенерируется

enter image description here

+0

Спасибо за это подробное объяснение, @JavaHopper! Это действительно помогает мне понять обработку памяти. У меня еще есть еще один вопрос: перед разрывом связи между ptr и ptr.next внутри цикла while мы фактически сделали simple.next/big.net указателем на узел, на который указывает ptr. Поскольку узел все еще имеет одну опорную точку, память не будет исправлена, не так ли? Итак, как это будет отличаться от перемещения ptr без нарушения? – GettingBetter

+0

Как вы могли видеть, если вы перемещаете ptr, не нарушая цепочку, отдельные узлы все еще связаны друг с другом, следовательно, не мусор, собранный после каждой итерации – JavaHopper

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