Shuffling algorithm is a common random problem that we often encounter when playing games and random sorting. It can be abstracted like this: get a random sequence array of all natural numbers within M.
Searching "Shuffling Algorithm" on Baidu, the first result is "Baidu Library-Shuffling Algorithm". After scanning the contents, many contents can easily mislead others into going astray, including the use of linked lists instead of arrays in the end. It is also only a limited optimization (linked lists also introduce a loss of read efficiency).
The first method in this article can be simply described as: randomly draw cards and put them in another group; draw them again. If you draw an empty card, repeat the draw.
"If you draw an empty card, draw it again." This will lead to an increasing chance of drawing an empty card later, which is obviously unreasonable.
It can be optimized in one step: after the cards are removed, the original cards will be reduced. (Instead of leaving an empty card)
The code is as follows:
//Draw one card each time and put it in another pile. Because you have to extract elements from the array and pull all subsequent elements forward by one, it is very time-consuming.
var arr2 = new Array();
for (var i=m; i>0; i--) {
var rnd = Math.floor(Math.random()*i);
arr2.push(arr[rnd]);
arr.splice(rnd,1);
}
return arr2;
}
This is also obviously problematic, because if the array is very large, deleting an element in the middle will cause the subsequent queue to move forward, which is a very time-consuming action.
Recall "Why do we delete that element?" The purpose is not to produce empty cards.
In addition to deleting that element, are there any other ways for us to remove empty cards?
----Yes, we just put the last undrawn card in the drawn position.
So, we can optimize this idea like this:
//Draw one card each time and put it in another pile. Place the last undrawn card on the empty seat.
var arr2 = new Array();
for (var i=m; i>0;) {
var rnd = Math.floor(Math.random()*i);
arr2 .push(arr[rnd]);
arr[rnd] = arr[--i];
}
return arr2;
}
//Swap the i-th card with any card after one round
for (var i=0; i
temp = arr[rnd];
arr[rnd] = arr[i];
arr[i]=temp;
}
return arr;
}
In addition to the idea of drawing and exchanging cards, we can also use the idea of inserting cards: there is one card first, the second card has two positions that can be randomly inserted (before or after the first card), and the third There are three positions for a card to be randomly inserted (at the back, or in the first place, or in the second place), and so on
The code is as follows:
The above code will also have some problems: as the number of cards increases, it becomes more and more difficult to insert cards, because inserting cards will cause many subsequent cards to be pushed back.
Of course, we can also optimize it appropriately: there are n-1 cards first, the n-th card is placed at the end, and then it swaps positions with any card.
The code is as follows:
Okay, the whole code is as follows. Interested students can try it on their own machines to see their respective execution efficiency and whether the final result is theoretically random.