前言
持续更新了
正文
问题来源
本问题来自leetcode上的384题。
问题描述
打乱一个没有重复元素的数组。
示例 1:
// 以数字集合 1, 2 和 3 初始化数组。
int[] nums = {1,2,3};
Solution solution = new Solution(nums);
// 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。
solution.shuffle();
// 重设数组到它的初始状态[1,2,3]。
solution.reset();
// 随机返回数组[1,2,3]打乱后的结果。
solution.shuffle();
分析:
shuffle这个算法我是知道的,然后我写完提交发现出错了,目前还不知道为何出错
type Solution struct {
reset []int
}
func Constructor(nums []int) Solution {
reset := make([]int, len(nums))
copy(reset, nums)
return Solution{reset}
}
/** Resets the array to its original configuration and return it. */
func (this *Solution) Reset() []int {
s := make([]int, len(this.reset))
copy(s, this.reset)
return s
}
/** Returns a random shuffling of the array. */
func (this *Solution) Shuffle() []int {
rand.Seed(time.Now().Unix())
s := make([]int, len(this.reset))
copy(s, this.reset)
for i := len(s)-1; i >= 0; i-- {
index := rand.Intn(i+1)
s[i], s[index] = s[index], s[i]
}
return s
}
同样的算法我用c++提交就对了,我也不知道是出现了什么问题
class Solution {
public:
Solution(vector<int> nums): v(nums) {}
/** Resets the array to its original configuration and return it. */
vector<int> reset() {
return v;
}
/** Returns a random shuffling of the array. */
vector<int> shuffle() {
vector<int> res = v;
for (int i = res.size()-1; i >= 0; --i) {
int t = rand() % (i+1);
swap(res[i], res[t]);
}
return res;
}
private:
vector<int> v;
};
然后我改成直接调用rand.Shuffle函数就能够通过
// 其他部分没有改动,只改了这个函数
func (this *Solution) Shuffle() []int {
a := make([]int, len(this.reset))
copy(a, this.reset)
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
return a
}
然后看看源码
func (r *Rand) Shuffle(n int, swap func(i, j int)) {
if n < 0 {
panic("invalid argument to Shuffle")
}
// Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
// Shuffle really ought not be called with n that doesn't fit in 32 bits.
// Not only will it take a very long time, but with 2³¹! possible permutations,
// there's no way that any PRNG can have a big enough internal state to
// generate even a minuscule percentage of the possible permutations.
// Nevertheless, the right API signature accepts an int n, so handle it as best we can.
i := n - 1
for ; i > 1<<31-1-1; i-- {
j := int(r.Int63n(int64(i + 1)))
swap(i, j)
}
for ; i > 0; i-- {
j := int(r.int31n(int32(i + 1)))
swap(i, j)
}
}
然后我测试了一下rand.Intn()的随机性
for j := 0; j < 100; j++ {
rand.Seed(time.Now().Unix()) // 这句话放在最外层和这里效果不一样
for i := 2; i >= 0; i-- {
fmt.Print(rand.Intn(i+1))
}
fmt.Println()
}
随机数种子在最外面时,能够保证随机性,而放在里面不能保证随机性。可是回到使用rand.Shuffle()函数又能保证随机性,得细看int31n函数实现。
然后把代码修改一下将随机数种子放在构造时初始化,则能够成功通过。
总结:
勤思考。
结语
不管怎么样好好加油。