【发布时间】:2015-03-30 09:26:09
【问题描述】:
您好,我在 Robert Sedgewick 的算法第 4 版中遇到了一个问题。
出队排序。解释你将如何对一副牌进行排序,唯一允许的操作是查看最上面两张牌的值,交换最上面两张牌,以及将最上面的一张牌移到牌组底部。
我希望有人能解释一下如何做到这一点,我真的迷路了。谢谢你
【问题讨论】:
您好,我在 Robert Sedgewick 的算法第 4 版中遇到了一个问题。
出队排序。解释你将如何对一副牌进行排序,唯一允许的操作是查看最上面两张牌的值,交换最上面两张牌,以及将最上面的一张牌移到牌组底部。
我希望有人能解释一下如何做到这一点,我真的迷路了。谢谢你
【问题讨论】:
与其想象一副牌有顶有底,不如想象一副纸牌排列成一个环。您可以想象在两张特定卡片之间放置一个标记,然后对应于牌组的顶部。你的“交换上面两张牌”的操作就是将两张牌交换到标记的左侧,而“将牌堆的顶部移到底部”的操作则对应于将标记向左移动一步。
鉴于此,您可以自然地调整冒泡排序以在此设置中工作。将环中的一个位置永久标记为起点。然后,重复执行以下操作:如果标记左侧的两张卡顺序不正确,则交换它们。然后,将标记向左移动一步。作为规则的一个例外,如果标记比标记的初始位置早一步,则不要进行比较。如果你在没有交换任何东西的情况下绕着圆圈转,你就完了!
在伪代码中,如下所示:
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.
希望这会有所帮助!
【讨论】:
这里有一个非常简单的解决方案,使用 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;
}
【讨论】:
我有一个对自己来说似乎非常简单的策略:
这与冒泡排序相同: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)
【讨论】: