【问题标题】:Sorting a deque using limited operations?使用有限的操作对双端队列进行排序?
【发布时间】:2015-03-30 09:26:09
【问题描述】:

您好,我在 Robert Sedgewick 的算法第 4 版中遇到了一个问题。

出队排序。解释你将如何对一副牌进行排序,唯一允许的操作是查看最上面两张牌的值,交换最上面两张牌,以及将最上面的一张牌移到牌组底部。

我希望有人能解释一下如何做到这一点,我真的迷路了。谢谢你

【问题讨论】:

    标签: algorithm sorting deque


    【解决方案1】:

    与其想象一副牌有顶有底,不如想象一副纸牌排列成一个环。您可以想象在两张特定卡片之间放置一个标记,然后对应于牌组的顶部。你的“交换上面两张牌”的操作就是将两张牌交换到标记的左侧,而“将牌堆的顶部移到底部”的操作则对应于将标记向左移动一步。

    鉴于此,您可以自然地调整冒泡排序以在此设置中工作。将环中的一个位置永久标记为起点。然后,重复执行以下操作:如果标记左侧的两张卡顺序不正确,则交换它们。然后,将标记向左移动一步。作为规则的一个例外,如果标记比标记的初始位置早一步,则不要进行比较。如果你在没有交换任何东西的情况下绕着圆圈转,你就完了!

    在伪代码中,如下所示:

    repeat the following until no swaps are made:
        counting from i = 1 to n - 1, inclusive:
           if the top two cards are out of order, swap them.
           move the top card of the deck to the bottom.
        then, move the top card of the deck to the bottom.
    

    希望这会有所帮助!

    【讨论】:

    • 这很有帮助,谢谢!!
    • 我们如何标记卡片?在提供的方法中,您不能访问卡片组内的任何数据,只能交换或移动到底部。
    • @CameronHall 这个方法的基本思路是正确的。而不是考虑“标记”,您可以这样做:首先,您迭代所有卡片并计算卡片的数量。比如说5张牌。然后你开始比较。最多需要比较4+3+2+1次。所以第一次,比较4次(你记录当前pass的比较次数),然后将最后一张卡片移到底部,然后开始下一个pass。第2次,比较3次,然后将2张牌移到底部,开始第3次迭代,以此类推。对于任何迭代,如果没有发生交换,则对其进行排序。
    【解决方案2】:

    这里有一个非常简单的解决方案,使用 java。只需通过比较和跟踪已排序元素的数量来不断移动顶部元素。在每次迭代中,它将根据位置为我们提供一个最小的元素。我们将根据 n 和 k 值来执行此操作。对于 n 值,我们将根据较大的元素继续移动,对于 k 值,我们将仅根据较小的值继续移动,最终,解决方案会出现。你可以试试这个。

    private void sort(Integer[] a) {
            int n = a.length-1,k=1;
            while (n>0){
                for (int i = 0; i < n; i++) {
                    if (a[1]>a[0]){
                        int temp = a[0];
                        a[0] = a[1];
                        a[1] = temp;
                    }
                    pushToBackAndShift(a);
                }
                for (int i = 0; i < k; i++) {
                    if (a[1]<a[0]){
                        int temp = a[0];
                        a[0] = a[1];
                        a[1] = temp;
                    }
                    pushToBackAndShift(a);
                }
                n--;k++;
            }
            pushToBackAndShift(a);
        }
    
    private void pushToBackAndShift(Integer[] a) {
            int temp = a[0];
            for (int i = 0; i < a.length-1; i++) {
                a[i] = a[i+1];
            }
            a[a.length-1] = temp;
        }

    【讨论】:

      【解决方案3】:

      我有一个对自己来说似乎非常简单的策略:

      这与冒泡排序相同:1)比较(可能交换)然后移动; 2)不要比较和移动(不要改变顺序)。并且两种动作在一轮中需要52步(甲板的长度)。

      条件一:

      def exchange_move(cards): 
          if cards[0] > cards[1]:
              cards[0], cards[1] = cards[1], cards[0]
              cards.append(cards.popleftL())
          else:    
              cards.append(cards.popleft())
      

      条件二:

      def move(cards): 
          cards.append(cards.popleft())
      

      并在每一轮中采取这两种行动:

      for i in range(card_len-skip):
          exchange_move(cards)
      for i in range(skip)
          move(cards)
      

      这是Python中的完整代码:

      from collections import deque
      import random
      from enum import Enum
      
      class Suit(Enum):
          __order__ = "spade heart club diamond"
          spade = 1
          heart = 2
          club = 3
          diamond = 4
      
      
      class Card(object):
          def __init__(self, suit, value):
              assert type(suit) == Suit
              assert value > 0 and value < 14
              self._suit = suit
              self._value = value
              self.value = self._get_value()
      
          def _get_value(self):
              return self._suit.value * 13 + self._value
      
          def __lt__(self, other):
              return self.value < other.value
      
          def __str__(self):
              return str((self._suit.name, self._value))
      
      cards = deque(maxlen=52)
      
      for s in Suit:
          for i in range(13):
              cards.append(Card(s, i+1))
      
      random.shuffle(cards)
      
      def is_sorted(cards):
          for i in range(len(cards)-2):
              if cards[i] > cards[i+1]:
                  return False
          return True
      
      def exchange_move(cards):
          if cards[0] > cards[1]:
              cards[0], cards[1] = cards[1], cards[0]
          cards.append(cards.popleft())
      
      def move(cards):
          cards.append(cards.popleft())
      
      skip = 0
      while(not is_sorted(cards)):
          if skip == len(cards):
              print('something strange happened')
          for i in range(len(cards)-skip):
              exchange_move(cards)
          for i in range(skip):
              move(cards)
          skip += 1
      
      for c in cards:
          print(c)
      

      【讨论】:

        猜你喜欢
        • 2014-06-01
        • 2013-03-17
        • 2011-07-05
        • 1970-01-01
        • 1970-01-01
        • 2012-05-20
        • 1970-01-01
        • 2017-04-11
        • 1970-01-01
        相关资源
        最近更新 更多