用 Rand7() 实现 Rand10() 用 Rand7() 实现 Rand10()
解题思路 原理
1 2 3 4 5 6 已知 rand_N() 可以等概率的生成[1, N]范围的随机数 那么: (rand_X() - 1) × Y + rand_Y() ==> 可以等概率的生成[1, X * Y]范围的随机数,即实现了rand_XY() rand_N() % Y +1 ==> 只要N是Y的倍数,就可以实现利用rand_N()实现rand_Y()
要实现rand10()
,就需要实现rand_N()
,并且保证N大于10且是10的倍数 。这样就可以通过rand_N() % 10 + 1
得到[1, 10]范围内的随机数了。
(rand7()-1) × 7 + rand7() ==> rand49()
,但是49不是10的倍数。这里就涉及到了“拒绝采样 ”的知识了,也就是说,如果某个采样结果不在要求的范围内,则丢弃它。
解题代码 1 2 3 4 5 6 7 8 func rand10 () int { for { num := (rand7()-1 ) * 7 + rand7() if num <= 40 { return num % 10 + 1 } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 func rand10 () int { for { a := rand7() b := rand7() num := (a-1 ) * 7 + b if num <= 40 { return num % 10 + 1 } a = num - 40 b = rand7() num = (a-1 ) * 7 + b if num <= 60 { return num % 10 + 1 } a = num - 60 b = rand7() num = (a-1 ) * 7 + b if num <= 20 { return num % 10 + 1 } } }
和为K的子数组 和为K的子数组
解题思路 前缀和 :preSum[i]
为数组第0
项到第i
项的和。数组第i
项到第j
项的和:nums[i] + ... + nums[j] = preSum[j] - preSum[i-1]
,令preSum[-1]=0
,使i=0
时成立。
使用一个哈希表 记录前缀和出现的次数,从前到后遍历数组,若当前的前缀和为preSum
,那么若前缀和为preSum-k
,则可以构成两个前缀和之差 为k
。
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func subarraySum (nums []int , k int ) int { hashMap := map [int ]int {} hashMap[0 ] = 1 preSum := 0 count := 0 for _, num := range nums { preSum += num if hashMap[preSum-k] > 0 { count += hashMap[preSum-k] } hashMap[preSum]++ } return count }
课程表 课程表
解题思路 利用拓扑排序 的思路,将选课过程看成是一次拓扑排序。某个课程的入度 即为先修课程数 ,用一个栈记录没有先修课的课程。则拓扑排序的过程如下:
计算初始时的入度/先修课程数
将没有先修课的课程推入栈中
当栈中不空时循环,弹出栈中的课程,选择该课程。删除所有该课程的出边,若在删除出边后,某个课程的入度为0,则将这个课程送入栈中。
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 func canFinish (numCourses int , prerequisites [][]int ) bool { inDegrees := make ([]int , numCourses) stack := make ([]int , numCourses) top := -1 count := 0 for _, prerequisite := range prerequisites { inDegrees[prerequisite[0 ]]++ } for course, inDegree := range inDegrees { if inDegree == 0 { top++ stack[top] = course } } for top >= 0 { course := stack[top] top-- count++ for _, prerequisite := range prerequisites { if prerequisite[1 ] == course { inDegrees[prerequisite[0 ]]-- if inDegrees[prerequisite[0 ]] == 0 { top++ stack[top] = prerequisite[0 ] } } } } return count == numCourses }
每日温度 每日温度
解题思路 利用单调栈 ,从栈底到栈顶的温度递减,栈中记录的是温度下标。从前向后遍历温度列表:
若栈为空或者符合单调栈的单调递减特性,则入栈
否则弹出栈中所有小于当前温度的元素,弹出元素的同时更新answer
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func dailyTemperatures (temperatures []int ) []int { answer := make ([]int , len (temperatures)) stack := make ([]int , len (temperatures)) top := -1 for i, temperature := range temperatures { if top < 0 || temperature <= temperatures[stack[top]] { top++ stack[top] = i } else { for top >= 0 && temperature > temperatures[stack[top]] { answer[stack[top]] = i-stack[top] top-- } top++ stack[top] = i } } return answer }