【问题标题】:Partitioning a linked list对链表进行分区
【发布时间】:2016-05-06 15:54:12
【问题描述】:

我正在尝试基于链表数据结构解决这个算法问题。问题如下:

给定一个链表和一个值 x,对它进行分区,使得所有小于 x 的节点都在大于或等于 x 的节点之前。 您应该保留两个分区中每个分区中节点的原始相对顺序。

例如,

给定 1->4->3->2->5->2 和 x = 3, 返回 1->2->2->4->3->5.

我的解决方法是:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode partition(ListNode head, int x) {
        if(head == null) return null;
        ListNode headNode = new ListNode(-1);
        headNode.next = head;

        ListNode tail = head;
        while(tail.next!=null){
            tail = tail.next;
        }
        ListNode actualTail = tail;
        ListNode current = headNode;
        while(current!=actualTail && current.next!=actualTail){
            if(current.next.val >= x && current.next!=tail){
                System.out.println("Moving "+current.next.val+" to end of list, ahead of "+tail.val);
                ListNode temp = current.next;
                current.next = current.next.next;
                tail.next = temp;
                tail = tail.next;
                tail.next = null;
            }else{
                current = current.next;    
            }

        }
        return headNode.next;
    }
}

虽然某些测试用例可以很好地使用上面提到的代码,但有一组测试用例失败了,因为我无法保持列表中节点的原始相对顺序。

例如: 列表 = [1->2] x = 0

我的结果: [2,1]

预期: [1,2]

任何帮助将不胜感激。

【问题讨论】:

  • 所有小于 x 的节点都在大于或等于 x 的节点之前。还要保留原来的相对顺序。

标签: algorithm data-structures linked-list


【解决方案1】:

我认为你可以用更简单的方式做到这一点:

  • 保留 2 个列表,一个用于较低节点,另一个用于较大节点。
  • 迭代列表,将节点添加到相应的列表中。
  • 将较小的列表与较大的列表连接

类似这样的:

public ListNode Partition(ListNode head, int x)
{
    ListNode lowerHead = null, lowerTail = null;              //Head and Tail of lower list
    ListNode greaterHead = null, greaterTail = null;          //Head and Tail of greater list

    ListNode current = head;

    while (current != null)
    {
        if (current.val < x)
        {
            if (lowerHead == null) lowerHead = current;      //If is the first node in the list
            if (lowerTail == null) lowerTail = current;      //set the head an tail to the same value
            else lowerTail = lowerTail.next = current;       //Otherwise, add the node and update the tail
        }
        else
        {
            if (greaterHead == null) greaterHead = current;  //If is the first node in the list
            if (greaterTail == null) greaterTail = current;  //set the head an tail to the same value
            else greaterTail = greaterTail.next = current;   //Otherwise, add the node and update the tail
        }

        current = current.next;
    }

    if (greaterHead != null)
        greaterTail.next = null;

    if (lowerHead == null) return greaterHead;
    else
    {
        lowerTail.next = greaterHead;
        return lowerHead;
    }
} 

由于节点在原始列表中出现时添加,因此顺序得以保留

【讨论】:

  • 作为附加要求,如果我们必须就地执行它怎么办。这就是我试图在我的方法中做的事情。
  • 其实in-place在这里有点混乱,因为只有next引用被改变(没有列表对象,只有节点互连)
【解决方案2】:

它可以在 O(N) 时间 O(1) 空间内完成。就收下吧 跟踪前一个节点,在第一个节点之前,即 大于或等于 X。

此节点充当小于 X 的节点之间的边界 以及大于或等于 X 的节点。

将代码与内联 cmets 一起引用。

    class Solution {
    public ListNode partition(ListNode head, int x) {
        // Assume that list has at least one instance of X and x = 3

        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode prev = dummy;
        ListNode curr = head;

        // Keeps track of the preceding node, before the first value greater than or equal to x.
        ListNode large = null;
        // Tracks weather the first node greater than or equal to x has been found.
        boolean isFirstLargeFound = false;

        while(curr != null) {
            if (curr.val >= x) {
                if (!isFirstLargeFound) {
                    large = prev;
                    isFirstLargeFound = true;    
                }
            } else if (isFirstLargeFound) {
                // If the current value is less than x and the first larger value has
                // been found, we need to swap the nodes.
                //
                // Consider the example: 1->4->0->3->2->5, the curr node is at value 0.
                // At this point of time the first larger value i.e. 4 has been already
                // found, hence we have to move the Node with value 0 to a place before 
                // the node with value 4.
                //
                // Before: 1->4->0->3->2->5
                // After: 1->0->4->3->2->5
                ListNode temp = large.next;
                prev.next = curr.next;
                large.next = curr;
                // Ensures that the first element that is >=X, is always next of large node.
                curr.next = temp;
                large = large.next;
            }

            prev = curr;
            curr = curr.next;
        }
        return dummy.next;
    }
}

【讨论】:

    【解决方案3】:

    我用 Python 解决了它并且工作正常。

    current = runner = ll.head
    while runner:
        if runner.value < part:
            temp = current.value
            current.value = runner.value
            runner.value = temp
    
            current = current.next
            runner = runner.next
        else:
            runner = runner.next
    

    【讨论】:

      【解决方案4】:

      尽管这是一个有点旧的线程,但我希望这对某人有用。

      class ListNode:
          def __init__(self, x):
              self.val = x
              self.next = None
      
      class LinkedList:
          def __init__(self):
              self.head = None
              self.tail = None
      
          def insert_node(self, val):
              new_node = ListNode(val)
              if self.head is None:
                  self.head = self.tail = new_node
              else:
                  self.tail.next = new_node
                  self.tail = new_node
      
      class Solution:
          def partition(self, head: ListNode, x: int) -> ListNode:
              if head is None or head.next is None:
                  return head
              else:
                  tmp = head
                  low = LinkedList()
                  high = LinkedList()
                  while tmp is not None:
                      if tmp.val < x:                    
                          low.insert_node(tmp.val)
                      else:
                          high.insert_node(tmp.val)
                      tmp = tmp.next
                  if low.head is not None:
                      tail = low.head
                      while tail.next is not None:
                          tail = tail.next
                      tail.next = high.head
                      output = low.head
                  else:
                      output = high.head
                  return output
      

      【讨论】:

        猜你喜欢
        • 2016-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-05
        相关资源
        最近更新 更多