- 洗牌
- 蓄水池
- 加权
洗牌
大致有四种写法
func shuffle(nums []int) []int {
n := len(nums)
for i := 0; i < n; i++ {
// [i, n - 1)
j := i + rand.Intn(n - i)
temp := nums[i]
nums[i] = nums[j]
nums[j] = temp
}
return nums
}
主要区别在于循环条件和循环体的第一句话
for i := 0; i < n -1; i++ {
j := i + rand.Intn(n-i)
// ...
}
for i := n -1; i >= 0; i-- {
j := rand.Intn(i)
// ...
}
for i := n -1; i> 0; i-- {
j := rand.Intn(i)
// ...
}
那么比较下第一种与第二种的区别。 区别就是,
第一种的产生结果数量有: n (n-1) … 1
第二种产生结果数量比第一种少了最后一个 i = n-1 的时候,当 i = n-1 的时候,取值范围是 [n-1, n-1] ,所以是 n (n-1) … 2
所以两者是一样的结果。
同理,第三种第四种类比。
蓄水池
func random (nums []int, k int) []int {
res := make([]int, k)
copy(res, nums)
n := len(nums)
for i:= k; i < n; i++ {
// [0, i+1) => [0, i]
j := rand.Intn(i)
if j < k {
res[j] = nums[i]
}
}
return res
}
加权
func searchInts(a []int, target int) int {
left, right := 0, len(a)-1
for left <= right {
mid := left + (right-left)>>1
if a[mid] >= target {
if mid == 0 || a[mid-1] < target {
return mid
}
right = mid - 1
} else {
left = mid + 1
}
}
return -1
}