Sorting a deque using limited operations?

后端 未结 3 699
庸人自扰
庸人自扰 2021-01-13 02:46

Hi I came across a question in the Algorithms 4th Edition by Robert Sedgewick.

Dequeue sort. Explain how you would sort a deck of cards, with the res

相关标签:
3条回答
  • 2021-01-13 03:18

    A very simple solution is here using java. Just keep shifting the top element by comparing and keep track of the number of sorted elements. On every iteration, it will give us one smallest element based on the position. We will do this based on n and k values. For n values, we will keep shifting based on bigger elements and for k values, we will just keep shifting based on smaller values and eventually, the solution will come. You can try this.

    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;
        }

    0 讨论(0)
  • 2021-01-13 03:29

    I have a strategy which seems very straightforward to myself:

    Consier this the same as the bubble sort: 1) compare(possibly swap) and then move; 2) dont' compare and move(don't change the order). And two kinds of actions take 52 steps(the length of the decks) in one round.

    Condition 1:

    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())
    

    Condition 2:

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

    And take these two kinds of actions in each round:

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

    And this is the complete code in 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)
    
    0 讨论(0)
  • 2021-01-13 03:37

    Rather than thinking of the deck having a top and a bottom, imagine that the deck of cards is arranged in a ring. You can imagine having a marker that you place between two specific cards, which then corresponds to the top of the deck. Your operations of "swap the top two cards" is then swapping the two cards to the left of the marker, and the operation of "move the top of the deck to the bottom" then corresponds to moving the marker one step to the left.

    Given this, you can naturally adapt bubble sort to work in this setup. Permanently mark one of the positions in the ring as the start point. Then, repeatedly do the following: if the two cards to the left of the marker are out of order, swap them. Then, move the marker one step to the left. As an exception to the rule, if the marker is one step before the marker's initial position, don't do the comparison. If you go around the circle without exchanging anything, you're done!

    In pseudocode, this would look as follows:

    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.
    

    Hope this helps!

    0 讨论(0)
提交回复
热议问题