리스트 랜덤 화 <T>


852

C #에서 일반 목록의 순서를 무작위로 만드는 가장 좋은 방법은 무엇입니까? 복권 유형 응용 프로그램을 위해 무작위 순서를 할당하고 싶은 목록에 유한 한 75 개의 숫자 세트가 있습니다.


3
이 기능을 .NET에 통합하기위한 공개적인 문제가 있습니다 : github.com/dotnet/corefx/issues/461
Natan

5
당신은에 관심이있을 수 있습니다 이 NuGet 패키지 에 대한 확장 방법을 포함, 셔플은 IList <T>과는 IEnumerable <T> 피셔 - 예이츠 알고리즘은 아래에 언급 된 사용
ChaseMedallion

3
@Natan은 누군가가 "많은 프로젝트를 수행하고 많은 라이브러리를 개발했으며 그런 방법이 필요하지 않았기 때문에"문제를 해결했습니다. 이제 우리 자신을 조사하고, 최상의 구현을 찾고, 단순히 바퀴를 재발 명하는 데 시간을 낭비해야합니다.
Vitalii Isaenko

1
이게 맞습니까? 10 년 후 유효한 단일 기능 답변이 아닙니까? 아마도 엔트로피의 양을 해결하고 75 개의 숫자 $ log2 (75!) = 364 $로 목록을 섞는 방법과 이것을 얻는 방법에 대한 또 다른 현상금이 필요할 것입니다. 피셔-야 테스 셔플 중에 적어도 한 번은 256 비트 엔트로피를 가진 암호로 안전한 RNG를 다시 시드해야합니다.
팔코

1
그리고 일반적인 코더가이 문제를 해결할 수 없다면, 우리 모두 가능한 0.01 %의 솔리테어 게임을 영원히 플레이 했습니까?
팔코

답변:


1135

어떤 셔플 (I)List에 기초 확장 방법 피셔 - 예이츠 셔플 :

private static Random rng = new Random();  

public static void Shuffle<T>(this IList<T> list)  
{  
    int n = list.Count;  
    while (n > 1) {  
        n--;  
        int k = rng.Next(n + 1);  
        T value = list[k];  
        list[k] = list[n];  
        list[n] = value;  
    }  
}

용법:

List<Product> products = GetProducts();
products.Shuffle();

위의 코드는 많은 비판 된 System.Random 메서드를 사용하여 스왑 후보를 선택합니다. 빠르지 만 무작위는 아닙니다. 셔플에서 더 나은 품질의 무작위성이 필요한 경우 System.Security.Cryptography의 난수 생성기를 사용하십시오.

using System.Security.Cryptography;
...
public static void Shuffle<T>(this IList<T> list)
{
    RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
    int n = list.Count;
    while (n > 1)
    {
        byte[] box = new byte[1];
        do provider.GetBytes(box);
        while (!(box[0] < n * (Byte.MaxValue / n)));
        int k = (box[0] % n);
        n--;
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
    }
}

이 블로그 (WayBack Machine) 에서 간단한 비교가 가능 합니다.

편집 : 몇 년 전에이 답변을 쓴 이후로 많은 사람들이 저의 의견이나 글을 써서 비교할 때 큰 바보 같은 결함을 지적했습니다. 물론 그렇습니다. 의도 한 방식으로 System.Random을 사용하는 경우 아무런 문제가 없습니다. 위의 첫 번째 예에서는 Shuffle 메서드 내에서 rng 변수를 인스턴스화하여 메서드를 반복적으로 호출해야하는지 문제를 묻습니다. 아래는 @weston이 오늘 여기에서받은 정말 유용한 의견을 바탕으로 한 고정 된 전체 예입니다.

Program.cs :

using System;
using System.Collections.Generic;
using System.Threading;

namespace SimpleLottery
{
  class Program
  {
    private static void Main(string[] args)
    {
      var numbers = new List<int>(Enumerable.Range(1, 75));
      numbers.Shuffle();
      Console.WriteLine("The winning numbers are: {0}", string.Join(",  ", numbers.GetRange(0, 5)));
    }
  }

  public static class ThreadSafeRandom
  {
      [ThreadStatic] private static Random Local;

      public static Random ThisThreadsRandom
      {
          get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
      }
  }

  static class MyExtensions
  {
    public static void Shuffle<T>(this IList<T> list)
    {
      int n = list.Count;
      while (n > 1)
      {
        n--;
        int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
      }
    }
  }
}

31
list.Count가> Byte.MaxValue이면 어떻게됩니까? n = 1000이면 255 / 1000 = 0이므로 box [0] <0이 항상 false이므로 do 루프는 무한 루프입니다.
AndrewS

18
비교에 결함이 있음을 지적하고 싶습니다. 루프에서 <code> new Random () </ code>을 사용하는 것이 <code> Random </ code>의 임의성이 아닌 문제입니다. 설명
Sven

9
임의 순서의 인스턴스를 임의 순서로 Shuffle을 빠르게 연속적으로 호출하는 것처럼 (예 : 짧은 목록을 많이 섞음) 내부를 생성하는 대신 Shuffle 메서드에 전달하는 것이 좋습니다. 방법 (예 : 첫 번째 항목은 항상 위치 3으로 이동).
마크 히스

7
그냥 만드는 Random rng = new Random();A는 static비교 게시물에 문제를 해결할 것입니다. 이후의 각 호출은 이전 호출에서 마지막 임의의 결과로 이어집니다.
weston

5
# 2, 바이트의 최대 범위가 255이기 때문에 Crypto 생성기가있는 버전이 작동하는지 확실하지 않으므로 그보다 큰 목록은 올바르게 섞이지 않습니다.
Mark Sowul

336

우리가 완전히 무작위 순서로 항목을 섞어 야 할 경우 (목록에 항목을 혼합하기 위해), guid별로 항목을 주문하는이 간단하지만 효과적인 코드를 선호합니다 ...

var shuffledcards = cards.OrderBy(a => Guid.NewGuid()).ToList();

40
GUID는 무작위가 아닌 고유해야합니다. 그것의 일부는 기계 기반이고 다른 일부는 시간 기반이며 작은 부분 만 무작위입니다. blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx
Despertar

99
이것은 훌륭한 우아한 솔루션입니다. guid 이외의 것이 임의성을 생성하기를 원한다면 다른 것으로 주문하십시오. 예 : var shuffledcards = cards.OrderBy(a => rng.Next()); compilr.com/grenade/sandbox/Program.cs
수류탄

20
안돼 이것은 잘못이다. "무작위 순서"는 완전히 뒤섞이지 않습니다. 편견을 도입하고 더 나빠 무한 루프에 빠질 위험이 있습니다
Vito De Tullio

77
@VitoDeTullio : 당신은 잘못 기억하고 있습니다. 무작위 비교 함수 를 제공하면 무한 루프 위험이 있습니다 . 일관된 총 주문 을 생성하려면 비교 기능이 필요합니다 . 임의의 는 괜찮습니다. 임의의 키로 정렬하는 기술 이 잘못되어 있지 않기 때문에 guid가 무작위로 보장되지 않기 때문에이 제안은 잘못되었습니다 .
Eric Lippert

24
@Doug : NewGuid유일한 GUID를 보장합니다. 무작위성을 보장하지 않습니다. 고유 한 값을 만드는 것 이외의 목적으로 GUID를 사용 하는 경우 잘못된 값을 사용하고 있습니다.
Eric Lippert

120

이 간단한 알고리즘의 모든 버전이 놀랍습니다. Fisher-Yates (또는 Knuth shuffle)는 약간 까다 롭지 만 매우 컴팩트합니다. 왜 까다로운가요? 난수 생성기 가 포함 또는 배타적 인 r(a,b)값을 반환 하는지 여부에주의를 기울여야하기 때문에 b. 또한 Wikipedia 설명 을 편집 하여 사람들이 의사 코드를 맹목적으로 따르지 않고 버그를 감지하기 어렵게 만들었습니다. .Net의 경우 더 이상 고민하지 않고 Random.Next(a,b)배타적 인 숫자를 반환합니다 b.C # / .Net에서 구현하는 방법은 다음과 같습니다.

public static void Shuffle<T>(this IList<T> list, Random rnd)
{
    for(var i=list.Count; i > 0; i--)
        list.Swap(0, rnd.Next(0, i));
}

public static void Swap<T>(this IList<T> list, int i, int j)
{
    var temp = list[i];
    list[i] = list[j];
    list[j] = temp;
}

이 코드를 사용해보십시오 .


카드를 교환 할 수 있도록 rnd (i, list.Count)를 rnd (0, list.Count)로 변경하는 것이 더 좋지 않습니까?
도넛

15
@ 도넛-아니요. 그렇게하면 셔플에 바이어스가 추가됩니다.
Shital Shah

2
Swap <T>을 별도의 방법으로 분리하면 temp에 불필요한 T 할당이 많이 발생하는 것처럼 보입니다.
Clay

2
나는 LINQ가 셔플 링의 성능을 잠재적으로 느리게 할 수 있으며, 특히 코드의 상대적 단순성 때문에 그것을 사용하지 않는 이유가 될 것이라고 주장했다.
winglerw28

7
언제 i = list.Count - 1, 즉 마지막 반복 rnd.Next(i, list.Count)은 내가 당신을 돌려 줄 것입니다. 따라서 i < list.Count -1루프 조건으로 필요 합니다. 글쎄, 당신은 그것을 필요로하지 않지만 1 반복을 절약합니다.)
Pod

78

IEnumerable의 확장 방법 :

public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
    Random rnd = new Random();
    return source.OrderBy<T, int>((item) => rnd.Next());
}

3
스레드 안전 목록에서 사용하더라도 스레드 안전은 아닙니다.
BlueRaja-Danny Pflughoeft

1
이 함수에 list <string>을 어떻게 주나요?
MonsterMMORPG 12

8
이 알고리즘에는 다음 두 가지 중요한 문제가 있습니다.- OrderByQuickSort 변형을 사용하여 항목을 임의적으로 (가시적으로 임의의) 키로 정렬합니다. QuickSort 성능은 O (N log N)입니다 . 반대로 Fisher-Yates 셔플은 O (N) 입니다. 75 개 요소의 컬렉션에 대해서는 큰 문제가되지 않지만 더 큰 컬렉션에 대해서는 그 차이가 뚜렷해집니다.
John Beyer

10
...- Random.Next()합리적인 의사 랜덤 분포 값을 생성 할 수 있지만 값이 고유하다는 보장 은 없습니다 . 중복 키의 확률은 N 이 2 ^ 32 + 1에 도달 할 때 확실성에 도달 할 때까지 N 과 비선형으로 증가 합니다. 이것은 QuickSort은이다 안정의 종류; 따라서 여러 요소에 동일한 의사 난수 인덱스 값이 할당되면 출력 순서의 순서는 입력 순서 와 동일 합니다. 따라서, "셔플"에 바이어스가 도입된다. OrderBy
John Beyer

27
@JohnBeyer : 그 편견보다 훨씬 더 큰 문제가 있습니다. Random에 40 억 개의 가능한 시드가 있으며, 이는 적당한 크기의 세트의 가능한 셔플 수보다 훨씬 적습니다. 가능한 셔플 중 아주 작은 부분 만 생성 될 수 있습니다. 이 바이어스는 우연한 충돌로 인한 바이어스를 줄입니다.
Eric Lippert

14

아이디어는 항목과 임의 순서로 익명 객체를 얻은 다음이 순서로 항목을 다시 정렬하고 값을 반환합니다.

var result = items.Select(x => new { value = x, order = rnd.Next() })
            .OrderBy(x => x.order).Select(x => x.value).ToList()

2
최고의 하나의 라이너 솔루션
vipin8169 7

1
당신은 끝에 fyi
reggaeguitar

rnd에 대해 잘 모르는 사람이 있으면 위의 코드보다 먼저 이것을 추가하십시오. rnd = new Random ();
Greg Trevellick

10
    public static List<T> Randomize<T>(List<T> list)
    {
        List<T> randomizedList = new List<T>();
        Random rnd = new Random();
        while (list.Count > 0)
        {
            int index = rnd.Next(0, list.Count); //pick a random item from the master list
            randomizedList.Add(list[index]); //place it at the end of the randomized list
            list.RemoveAt(index);
        }
        return randomizedList;
    }


4
var listCopy = list.ToList()들어오는 목록에서 모든 항목이 튀어 나오는 것을 피하고 싶지 않은가? 나는 왜 당신이 그 목록을 비우고 싶은지 알지 못합니다.
Chris Marisic

9

편집RemoveAt내 이전 버전의 약점이다. 이 솔루션은이를 극복합니다.

public static IEnumerable<T> Shuffle<T>(
        this IEnumerable<T> source,
        Random generator = null)
{
    if (generator == null)
    {
        generator = new Random();
    }

    var elements = source.ToArray();
    for (var i = elements.Length - 1; i >= 0; i--)
    {
        var swapIndex = generator.Next(i + 1);
        yield return elements[swapIndex];
        elements[swapIndex] = elements[i];
    }
}

선택 사항입니다 Random generator. 기본 프레임 워크 구현이 Random스레드에 안전하지 않거나 필요에 따라 암호화 방식으로 강력하지 않은 경우 구현에 작업을 삽입 할 수 있습니다.

스레드 안전 암호화 방식으로 강력한 Random구현에 적합한 구현 이이 답변에서 찾을 수 있습니다.


아이디어가 있습니다. (Ihope) 효율적인 방법으로 IList를 확장하십시오.

public static IEnumerable<T> Shuffle<T>(this IList<T> list)
{
    var choices = Enumerable.Range(0, list.Count).ToList();
    var rng = new Random();
    for(int n = choices.Count; n > 1; n--)
    {
        int k = rng.Next(n);
        yield return list[choices[k]];
        choices.RemoveAt(k);
    }

    yield return list[choices[0]];
}


stackoverflow.com/questions/4412405/…를 참조하십시오 . 당신은 이미 알고 있어야합니다.
nawfal

@nawfal 개선 된 구현을 참조하십시오.
Jodrell

1
흠. 그것은인가 GetNext또는 Next?
nawfal

4

이 간단한 확장 방법을 사용하여 달성 할 수 있습니다

public static class IEnumerableExtensions
{

    public static IEnumerable<t> Randomize<t>(this IEnumerable<t> target)
    {
        Random r = new Random();

        return target.OrderBy(x=>(r.Next()));
    }        
}

다음을 수행하여 사용할 수 있습니다

// use this on any collection that implements IEnumerable!
// List, Array, HashSet, Collection, etc

List<string> myList = new List<string> { "hello", "random", "world", "foo", "bar", "bat", "baz" };

foreach (string s in myList.Randomize())
{
    Console.WriteLine(s);
}

3
Random클래스 인스턴스를 함수 외부의 static변수 로 유지합니다 . 그렇지 않으면 빠른 연속으로 호출되면 타이머에서 동일한 무작위 시드를 얻을 수 있습니다.
Lemonseed 2016 년

흥미로운 메모-루프 내에서 랜덤 클래스를 신속하게 인스턴스화하면 서로 0ms에서 200ms 사이에 동일한 랜덤 화 시드를 얻을 가능성이 매우 높아 결과가 반복됩니다. 그러나 Random rand = new Random (Guid.NewGuid (). GetHashCode ());를 사용하여이 문제를 해결할 수 있습니다. 이것은 효과적으로 Guid.NewGuid ()로부터 도출되는 랜덤 강제
Baaleos

4

이것은 원본을 수정하지 않는 것이 좋을 때 선호하는 셔플 방법입니다. 열거 가능한 시퀀스에서 작동 하는 Fisher–Yates "내부"알고리즘 의 변형입니다 (길이 source를 처음부터 알 필요는 없음).

public static IList<T> NextList<T>(this Random r, IEnumerable<T> source)
{
  var list = new List<T>();
  foreach (var item in source)
  {
    var i = r.Next(list.Count + 1);
    if (i == list.Count)
    {
      list.Add(item);
    }
    else
    {
      var temp = list[i];
      list[i] = item;
      list.Add(temp);
    }
  }
  return list;
}

이 알고리즘은의 범위를 할당함으로써 구현 될 수있다 0length - 1 임의로 모든 인덱스가 정확하게 한번 선택 될 때까지 마지막 인덱스와 무작위로 선택된 인덱스를 교환하여 인덱스를 배기. 위의 코드는 똑같은 작업을 수행하지만 추가 할당은 수행하지 않습니다. 꽤 깔끔합니다.

Random클래스 와 관련하여 범용 번호 생성기입니다 (추첨을 실행하는 경우 다른 것을 사용하는 것이 좋습니다). 또한 기본적으로 시간 기반 시드 값에 의존합니다. 문제의 작은 완화는 Random클래스 를 시드하는 것 입니다. RNGCryptoServiceProvider또는 RNGCryptoServiceProvider이와 유사한 방법으로 (아래 참조)를 사용하여 균일하게 선택된 임의의 이중 부동 소수점 값을 생성 할 수 있지만 복권을 실행하면 임의성과 특성을 이해해야합니다. 무작위성 소스.

var bytes = new byte[8];
_secureRng.GetBytes(bytes);
var v = BitConverter.ToUInt64(bytes, 0);
return (double)v / ((double)ulong.MaxValue + 1);

랜덤 배가 (0과 1 사이)를 생성하는 점은 정수 솔루션으로 스케일링하는 데 사용하는 것입니다. 무작위 배정 x을 기반으로 목록에서 무언가를 선택해야 할 경우 항상 0 <= x && x < 1앞으로 나아갈 것입니다.

return list[(int)(x * list.Count)];

즐겨!


4

two를 사용하는 것이 마음에 들지 않는다면 Lists아마도 가장 쉬운 방법이지만 아마도 가장 효율적이거나 예측할 수없는 방법은 아닙니다.

List<int> xList = new List<int>() { 1, 2, 3, 4, 5 };
List<int> deck = new List<int>();

foreach (int xInt in xList)
    deck.Insert(random.Next(0, deck.Count + 1), xInt);

3

고정 번호 (75)가있는 경우 75 개의 요소가있는 배열을 만든 다음 요소를 배열의 무작위 위치로 이동하여 목록을 열거 할 수 있습니다. Fisher-Yates shuffle을 사용하여 목록 번호와 배열 인덱스의 매핑을 생성 할 수 있습니다 .


3

나는 보통 다음을 사용합니다.

var list = new List<T> ();
fillList (list);
var randomizedList = new List<T> ();
var rnd = new Random ();
while (list.Count != 0)
{
    var index = rnd.Next (0, list.Count);
    randomizedList.Add (list [index]);
    list.RemoveAt (index);
}

list.RemoveAt는이 구현을 엄청나게 느리게하는 O (n) 작업입니다.
George Polevoy

1
    List<T> OriginalList = new List<T>();
    List<T> TempList = new List<T>();
    Random random = new Random();
    int length = OriginalList.Count;
    int TempIndex = 0;

    while (length > 0) {
        TempIndex = random.Next(0, length);  // get random value between 0 and original length
        TempList.Add(OriginalList[TempIndex]); // add to temp list
        OriginalList.RemoveAt(TempIndex); // remove from original list
        length = OriginalList.Count;  // get new list <T> length.
    }

    OriginalList = new List<T>();
    OriginalList = TempList; // copy all items from temp list to original list.

0

다음은 섞인 값의 바이트 배열을 반환하는 효율적인 Shuffler입니다. 필요한 것 이상을 섞지 않습니다. 이전에 중단 한 곳부터 다시 시작할 수 있습니다. 내 실제 구현 (표시되지 않음)은 사용자 지정 교체 셔플 러를 허용하는 MEF 구성 요소입니다.

    public byte[] Shuffle(byte[] array, int start, int count)
    {
        int n = array.Length - start;
        byte[] shuffled = new byte[count];
        for(int i = 0; i < count; i++, start++)
        {
            int k = UniformRandomGenerator.Next(n--) + start;
            shuffled[i] = array[k];
            array[k] = array[start];
            array[start] = shuffled[i];
        }
        return shuffled;
    }

`


0

이를 수행하는 스레드 안전 방법은 다음과 같습니다.

public static class EnumerableExtension
{
    private static Random globalRng = new Random();

    [ThreadStatic]
    private static Random _rng;

    private static Random rng 
    {
        get
        {
            if (_rng == null)
            {
                int seed;
                lock (globalRng)
                {
                    seed = globalRng.Next();
                }
                _rng = new Random(seed);
             }
             return _rng;
         }
    }

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
    {
        return items.OrderBy (i => rng.Next());
    }
}

0
 public Deck(IEnumerable<Card> initialCards) 
    {
    cards = new List<Card>(initialCards);
    public void Shuffle() 
     }
    {
        List<Card> NewCards = new List<Card>();
        while (cards.Count > 0) 
        {
            int CardToMove = random.Next(cards.Count);
            NewCards.Add(cards[CardToMove]);
            cards.RemoveAt(CardToMove);
        }
        cards = NewCards;
    }

public IEnumerable<string> GetCardNames() 

{
    string[] CardNames = new string[cards.Count];
    for (int i = 0; i < cards.Count; i++)
    CardNames[i] = cards[i].Name;
    return CardNames;
}

Deck deck1;
Deck deck2;
Random random = new Random();

public Form1() 
{

InitializeComponent();
ResetDeck(1);
ResetDeck(2);
RedrawDeck(1);
 RedrawDeck(2);

}



 private void ResetDeck(int deckNumber) 
    {
    if (deckNumber == 1) 
{
      int numberOfCards = random.Next(1, 11);
      deck1 = new Deck(new Card[] { });
      for (int i = 0; i < numberOfCards; i++)
           deck1.Add(new Card((Suits)random.Next(4),(Values)random.Next(1, 14)));
       deck1.Sort();
}


   else
    deck2 = new Deck();
 }

private void reset1_Click(object sender, EventArgs e) {
ResetDeck(1);
RedrawDeck(1);

}

private void shuffle1_Click(object sender, EventArgs e) 
{
    deck1.Shuffle();
    RedrawDeck(1);

}

private void moveToDeck1_Click(object sender, EventArgs e) 
{

    if (listBox2.SelectedIndex >= 0)
    if (deck2.Count > 0) {
    deck1.Add(deck2.Deal(listBox2.SelectedIndex));

}

    RedrawDeck(1);
    RedrawDeck(2);

}

2
스택 오버플로에 오신 것을 환영합니다! 거대한 코드 블록이 아닌 답변에 설명을 추가하십시오. 여기서 우리의 목표는 사람들이 답을 이해하고 다른 상황에 적용 할 수 있도록 교육시키는 것입니다. 코드에 주석을 달고 설명을 추가하면 이번에 질문 한 사람뿐만 아니라 앞으로 같은 문제가있는 사람에게도 도움이됩니다.
starsplusplus

4
이 코드의 대부분은이 질문과 관련이 없으며, 유일하게 유용한 부분은 기본적으로 거의 6 년 전의 Adam Tegen의 답변을 반복합니다.
TC

0

제자리에서 작업하는 대신 새 목록을 반환하고 다른 많은 Linq 메서드가 수행 하는 것보다 더 일반적인 것을 허용 하는 수락 된 대답 의 간단한 수정 IEnumerable<T>.

private static Random rng = new Random();

/// <summary>
/// Returns a new list where the elements are randomly shuffled.
/// Based on the Fisher-Yates shuffle, which has O(n) complexity.
/// </summary>
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> list) {
    var source = list.ToList();
    int n = source.Count;
    var shuffled = new List<T>(n);
    shuffled.AddRange(source);
    while (n > 1) {
        n--;
        int k = rng.Next(n + 1);
        T value = shuffled[k];
        shuffled[k] = shuffled[n];
        shuffled[n] = value;
    }
    return shuffled;
}


-5

확실히 오래된 게시물이지만 GUID를 사용합니다.

Items = Items.OrderBy(o => Guid.NewGuid().ToString()).ToList();

GUID는 항상 고유하며 결과가 매번 변경 될 때마다 재생성되므로 GUID는 항상 고유합니다.


작지만 연속적인 newGuid를 고품질 무작위로 분류하는 방법에 대한 참조가 있습니까? quid / uuid의 일부 버전에는 타임 스탬프 및 기타 비 랜덤 부품이 있습니다.
Johan Lundberg

8
이 답변은 이미 주어졌으며, 무작위가 아닌 독창성을 위해 설계되었습니다.
Alex Angas

-7

이러한 종류의 문제에 대한 매우 간단한 접근 방식은 목록에서 여러 개의 임의 요소 스왑을 사용하는 것입니다.

의사 코드에서 이것은 다음과 같습니다.

do 
    r1 = randomPositionInList()
    r2 = randomPositionInList()
    swap elements at index r1 and index r2 
for a certain number of times

1
이 접근법의 한 가지 문제점은 언제 중지해야하는지 아는 것입니다. 또한 의사 난수 생성기에서 바이어스를 과장하는 경향이 있습니다.
Mark Bessey

3
예. 매우 비효율적입니다. 더 빠르고 더 빠른 접근 방식이 존재하는 경우 이와 같은 접근 방식을 사용할 이유가 없습니다.
PeterAllenWebb

1
매우 효율적이거나 효과적이지 않습니다 ... N 번 실행하면 많은 요소가 원래 위치에 남아있을 수 있습니다.
NSjonas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.