剑指Offer专项突击版题解八

71.按权重生成随机数

思考:说到平均的生成随机数,想到了水塘抽样法和彩票调度法。

水塘抽样算法适合于样本不确定,乃至于是变化的,每个样本的概率是一样的。

// 样本nums[],每个元素的被抽到的概率是一样的
index := 0 
for i := 1; i <= len(nums); i++{
    if rand.Intn(i) == 0{
        index = nums[i-1]
    }
}
return index

彩票调度算法是一种类似于将概率体现在数轴上面,适用范围是样本已知。

nums [] // 表示每个样本的概率
sum := 0 // 表示总的概率数
for i := 0 ; i < len(nums); i++{
    sum += nums[i]
}
r := rand.Intn(sum) // 平均的随机从0-sum-1取出一个数
cv := 0 // 表示当前所处的位置
for i := 0; i < len(nums); i++{
    cv += nums[i]
    if cv > r{ // 获取被抽中的下标
       return i
    }
}

72.求平方根

思想:二分查找、牛顿迭代法。

func mySqrt(x int) int {
    if x == 0 {
        return 0
    }
    C, x0 := float64(x), float64(x)
    for {
        if math.Abs(x0 - xi) < 1e-7 {
            break
        }
        x0 = xi
    }
    return int(x0)
}

73.狒狒吃香蕉

思想:二分查找思想,因为目标答案明确。

74.合并区间

思想:按照区间排序之后再进行合并。

75.数组相对排序

思想:借助map存储排序的权制,在通过内置函数sort.Sllice进行排序。

76.数组中的第 k 大的数字

思想:快排序定位

77.链表排序

思路:暴力思路,将节点放到数组内然后进行排序。

进阶:归并排序的思想。

func sortList(head *ListNode) *ListNode {
    var mergeSort func(left, right *ListNode) *ListNode
    merge := func(left, right *ListNode) *ListNode {
        res := &ListNode{}
        tail := res
        for left != nil && right != nil{
            if left.Val > right.Val {
                tep := right
                right = right.Next
                tep.Next = nil
                tail.Next = tep
                tail = tep
            }else {
                tep := left
                left = left.Next
                tep.Next = nil
                tail.Next = tep
                tail = tep
            }
        }
        if left != nil{
            tail.Next = left
        }
        if right != nil{
            tail.Next = right
        }
        return res.Next
    }
    // 左闭右开
    mergeSort = func(left, right *ListNode) *ListNode {
        if left == nil {
            return nil
        }
        if left.Next == right {
            left.Next = nil
            return left
        }
        fast := left
        low := left
        for fast != right {
            low = low.Next
            fast = fast.Next
            if fast != right {
                fast = fast.Next
            }
        }
        mid := low
        return merge(mergeSort(left, mid), mergeSort(mid, right))
    }
    return mergeSort(head, nil)
}

 

78.合并排序链表

思路:归并思路好,如果采用普通的解法去做,进行循环遍历也能得出结果,但是时间复杂度比较高。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeKLists(lists []*ListNode) *ListNode {
    merge := func (a , b *ListNode)*ListNode{
        res := &ListNode{}
        tail := res
        for a != nil && b != nil{
            if a.Val > b.Val{
                tep := b
                b = b.Next
                tail.Next = tep
                tail = tep
            }else {
                tep := a
                a = a.Next
                tail.Next = tep
                tail = tep
            }
        }
        if a != nil{
            tail.Next = a
        }
        if b != nil{
            tail.Next = b
        }
        return res.Next
    }
    var MegerSort func(left , right int)*ListNode
    MegerSort = func (left , right int)*ListNode{
        if left == right{
            return lists[left]
        }
        mid := left + (right - left) / 2
        return merge(MegerSort(left , mid) , MegerSort(mid + 1 , right))
    }
    if len(lists) == 0{
        return nil
    }
    return MegerSort(0 , len(lists)-1)
}

79.所有子集

思路:dfs

80.含有 k 个元素的组合

思路:dfs

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿联爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值