初级会员
  • 第 6572 位会员
  • wwwqjpcom
  • 1035367029@qq.com
  • 2016-10-30 13:29:34
  • Offline
  • 19 85

最近发布的主题

    暂无

最近发布的文章

    暂无

最近分享的资源

    暂无

最近发布的项目

    暂无

最近的评论

  • #38 @wwwqjpcom 优化了一下,1、修改数组为数组切片,这样直接使用copy,不再自己一个个移动赋值复制。2、优化了查找方法 ``` package suanfa import ( "fmt" "time" ) //获取前10000个素因子只有2 3 5的数 主要的优化 1、数组移动改为切片,整段copy 不再一个个赋值移动 //2、改动查找i2 i3的方法,根据上次的查找i2 i3的下标来查,实际每次查找1-2次 func Run4() { a := make([]uint64, 10002) a[0] = 2 a[1] = 3 a[2] = 5 maxi := 2 //最大值的索引 start2 := 0 start3 := 0 var a2 uint64 var a3 uint64 var a5 uint64 p := time.Now() for i := 0; i < 9999; i++ { c := a[i] a2 = c * 2 if a[9999] != 0 && a2 >= a[9999] { break } a3 = c * 3 a5 = c * 5 start2, start3, maxi = sortInsert4(a, a2, a3, a5, start2, start3, maxi) //插入3个数 //fmt.Println(a[:maxi+1]) } q := time.Now() fmt.Println(q.Sub(p).Nanoseconds()) //fmt.Println(a[:maxi+1]) fmt.Println(a[9999]) } func sortInsert4(a []uint64, a2 uint64, a3 uint64, a5 uint64, start2 int, start3 int, maxi int) (int, int, int) { //fmt.Println(a2, a3, a5, start2, start3, maxi) //a5肯定在最后。 插入a2和a3 查找 从后往前移动插入 i2 := 0 i3 := 0 //插入的数量 是1或者2 insert := 0 //搜索i2的位置 i := 0 for i = start2; i <= maxi; i++ { if a2 <= a[i] { break } } if a2 != a[i] { insert++ } i2 = i //搜索i3的位置 实际顶多比较几次就找到 for i = start3; i <= maxi; i++ { if a3 <= a[i] { break } } if a3 != a[i] { insert++ } i3 = i //fmt.Println(start2, i2, start3, i3, maxi) //由这打印出的可以看出,每次查找i2 i3顶多查找1-2次 if maxi+insert <= 9999 { copy(a[i3+insert:maxi+insert+1], a[i3:maxi+1]) } else if i3+insert <= 9999 { copy(a[i3+insert:9999], a[i3:10000]) } maxi = maxi + insert if a[i3] != a3 { insert-- a[i3+insert] = a3 } if insert != 0 { copy(a[i2+1:i3+1], a[i2:i3]) a[i2] = a2 } //fmt.Println(a[:maxi+1]) maxi++ if maxi <= 9999 { a[maxi] = a5 //a5一定是最大值,追加在末尾 } else { maxi = 9999 } return i2, i3, maxi } ``` 优化后在我电脑上计算到第10000个在1毫秒内。
  • 代码如下: ```go package suanfa import ( "fmt" "time" ) //获取前10000个素因子只有2 3 5的数 func Run() { var count int = 0 count++ var a [10002]uint64 = [10002]uint64{2, 3, 5} maxi := 2 //最大值的索引 var a2 uint64 var a3 uint64 var a5 uint64 p := time.Now() for i := 0; i < 9999; i++ { c := a[i] a2 = c * 2 if a[9999] != 0 && a2 >= a[9999] { break } a3 = c * 3 a5 = c * 5 maxi = sortInsert(&a, a2, a3, a5, i, maxi) //插入3个数 //fmt.Println(a[:maxi+1]) } q := time.Now() fmt.Println(q.Sub(p)) //fmt.Println(a[:maxi+1]) fmt.Println(a[9999]) } func sortInsert(a *[10002]uint64, a2 uint64, a3 uint64, a5 uint64, start int, maxi int) int { //fmt.Println(a2, a3, a5) //二分查找法查找 从后往前移动插入 //a5肯定在最后。 插入a2和a3 i2 := 0 i3 := 0 //插入 insert := 0 //搜索i2的位置 i := 0 j := start k := maxi for i = (start + maxi) / 2; j <= k; i = (j + k) / 2 { if a2 == a[i] { //找到了 i2 = i break } if a2 > a[i] { j = i + 1 } if a2 < a[i] { k = i - 1 } } //fmt.Println(i2) if i2 == 0 { //说明没找到啊 if a[i] < a2 { i2 = i + 1 } else { i2 = i } insert++ } //搜索i3的位置 j = i2 k = maxi for i = (j + k) / 2; j <= k; i = (j + k) / 2 { if a3 == a[i] { //找到了 i3 = i break } if a3 > a[i] { j = i + 1 } if a3 < a[i] { k = i - 1 } } //fmt.Println(i3) if i3 == 0 { //说明没找到啊 if a[i] < a3 { i3 = i + 1 } else { i3 = i } insert++ } //fmt.Println(i2, i3, insert, maxi) for i = maxi; i >= i3; i-- { if i+insert <= 9999 { a[i+insert] = a[i] //需要考虑i+insert > 10000的情况? } } maxi = maxi + insert if a[i3] != a3 { insert-- a[i3+insert] = a3 } //fmt.Println(a[:maxi+1]) if insert != 0 { for i := i3 - 1; i >= i2; i-- { a[i+1] = a[i] } a[i2] = a2 } //fmt.Println(a[:maxi+1]) maxi++ if maxi <= 9999 { a[maxi] = a5 //a5一定是最大值,追加在末尾 } else { maxi = 9999 } return maxi } ```
  • 试了一下, 没用其他数据结构的,直接就一个长度为10002的数组完成了,非暴力遍历,也不需要额外的空间。 个人电脑上2-3毫秒计算到第10000个。。。 ![image.png](https://static.studygolang.com/180810/1b91e0d90e2b0acc2e60188195b6d5ca.png)
  • 评论了主题 函数
    #1 @wwwqjpcom 可以看下 Go语言编程 的3.1.1章节--为类型添加方法。
  • 评论了主题 函数
    (f *File)表示这个函数属于 File类型,是File下的方法。 buf []byte 是入参, n,err是返回值,n是读取的直接长度。 如果没有出错,则err是空值nil