Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ba69e98d5 | |||
| 092ab58276 | |||
| 00ada130fa | |||
| 8dbfebe5be | |||
| 1aa86ce5b8 | |||
| ed71f9b607 | |||
| 351df675bd | |||
| dc5d924a2c | |||
| 74dd19c675 | |||
| 39cee0ce6a |
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 16:46
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package numberList
|
||||
|
||||
type i interface {
|
||||
Doc() string
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/18 13:08
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
type OnlyOneNumberOtherKObj struct{}
|
||||
|
||||
func (*OnlyOneNumberOtherKObj) Doc() string {
|
||||
return `
|
||||
给定一个整型数组 arr和一个大于1的整数k。已知 arr中只有1个数出现了1次,其他的数都出现了k次,请返回只出现了1次的数。
|
||||
|
||||
【要求】
时间复杂度为 O(N),额外空间复杂度为 O(1)。
|
||||
`
|
||||
}
|
||||
|
||||
func OnlyOneNumberOtherK(numList []int, k int) int {
|
||||
bitList := make([]int, 32)
|
||||
for _, num := range numList {
|
||||
//把每个数字转换成二进制
|
||||
store := make([]int, 32)
|
||||
for i := 0; num != 0; i++ {
|
||||
store[i] = num % k
|
||||
num = num / k
|
||||
}
|
||||
|
||||
for j := 0; j < 32; j++ {
|
||||
//不进位加法
|
||||
bitList[j] = (store[j] + bitList[j]) % k
|
||||
}
|
||||
}
|
||||
|
||||
//k进制转换回十进制
|
||||
power := 1 //k的次方值
|
||||
result := 0 //只出现一次的数字
|
||||
for i, bit := range bitList {
|
||||
power = 1
|
||||
for j := 0; j < i; j++ {
|
||||
power = power * k
|
||||
}
|
||||
|
||||
result = result + power*bit
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/18 13:09
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOnlyOneNumberOtherK(t *testing.T) {
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 3, 4, 2, 3, 4}, 2)) //1
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 3, 4, 2, 3, 4, 2, 3, 4}, 3)) //1
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 3, 4, 4, 5, 6, 2, 2, 3, 5, 5, 3, 4, 6, 6}, 3)) //1
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, 10)) //1
|
||||
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{2, 3, 3000, 4, 2, 3, 4}, 2)) //3000
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{2, 3, 4, 2, 9999, 3, 4, 2, 3, 4}, 3)) //9999
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{2, 3, 4, 4, 5, 6, 321, 2, 2, 3, 5, 5, 3, 4, 6, 6}, 3)) //321
|
||||
fmt.Println(OnlyOneNumberOtherK([]int{2, 2, 2, 2, 2, 2, 2, 5891, 2, 2, 2}, 10)) //5891
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 21:53
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
type OnlyOneNumberOtherThreeObj struct{}
|
||||
|
||||
func (*OnlyOneNumberOtherThreeObj) Doc() string {
|
||||
return `
|
||||
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
|
||||
要求:线性时间复杂度。 不使用额外空间来实现
|
||||
`
|
||||
}
|
||||
|
||||
func OnlyOneNumberOtherThree1(numList []int) int {
|
||||
bitList := make([]int, 32)
|
||||
|
||||
for _, num := range numList {
|
||||
for i := 0; i < 32; i++ {
|
||||
bitList[i] += (num >> i) & 1
|
||||
}
|
||||
}
|
||||
|
||||
res := 0
|
||||
|
||||
for i := 0; i < 32; i++ {
|
||||
if bitList[i]%3 != 0 {
|
||||
res += 1 << i
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
//通过二进制的方式,本质上就是要构造一个相应的回路,即出现num的次数分别从1~3应该是 01 -> 10 -> 00 ...
|
||||
func OnlyOneNumberOtherThree2(numList []int) int {
|
||||
|
||||
var a uint
|
||||
var b uint
|
||||
|
||||
//第一次出现num计算的结果 a = num ,b = 0
|
||||
//第二次出现num计算的结果 a = 0 ,b = num
|
||||
//第三次出现num计算的结果 a = num ,b = 0
|
||||
//因此直接返回a即可
|
||||
for _, num := range numList {
|
||||
a = a ^ uint(num)&(^b)
|
||||
b = b ^ uint(num)&(^a)
|
||||
}
|
||||
return int(a)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 21:55
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOnlyOneNumberOtherThree1(t *testing.T) {
|
||||
fmt.Println(OnlyOneNumberOtherThree1([]int{1, 1, 1, 2, 2, 2, 3, 3, 3, 4})) //4
|
||||
fmt.Println(OnlyOneNumberOtherThree1([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 4})) //4
|
||||
fmt.Println(OnlyOneNumberOtherThree1([]int{1, 15, 23, 67, 15, 67, 67, 23, 23, 14, 15, 1, 1})) //14
|
||||
fmt.Println(OnlyOneNumberOtherThree1([]int{100, 200, 300, 4, 6, 100, 100, 6, 6, 4, 200, 300, 200, 300, 5, 4})) //5
|
||||
}
|
||||
|
||||
func TestOnlyOneNumberOtherThree2(t *testing.T) {
|
||||
fmt.Println(OnlyOneNumberOtherThree2([]int{1, 1, 1, 2, 2, 2, 3, 3, 3, 4})) //4
|
||||
fmt.Println(OnlyOneNumberOtherThree2([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 4})) //4
|
||||
fmt.Println(OnlyOneNumberOtherThree2([]int{1, 15, 23, 67, 15, 67, 67, 23, 23, 14, 15, 1, 1})) //14
|
||||
fmt.Println(OnlyOneNumberOtherThree2([]int{100, 200, 300, 4, 6, 100, 100, 6, 6, 4, 200, 300, 200, 300, 5, 4})) //5
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 17:51
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
type OnlyOneNumberShowOnceObj struct{}
|
||||
|
||||
func (*OnlyOneNumberShowOnceObj) Doc() string {
|
||||
return `
|
||||
一个整型数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1)。
|
||||
`
|
||||
}
|
||||
|
||||
//通过异或解决
|
||||
func OnlyOneNumberShowOnce(numberList []int) int {
|
||||
result := 0
|
||||
for _, num := range numberList {
|
||||
result ^= num
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 17:52
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOnlyOneNumberShowOnce(t *testing.T) {
|
||||
fmt.Println(OnlyOneNumberShowOnce([]int{1, 2, 3, 2, 3, 4, 4})) //1
|
||||
fmt.Println(OnlyOneNumberShowOnce([]int{1, 2, 3, 2, 3, 4, 4, 1, 5})) //5
|
||||
fmt.Println(OnlyOneNumberShowOnce([]int{1, 2, 3, 2, 3, 4, 4, 1, 10})) //10
|
||||
fmt.Println(OnlyOneNumberShowOnce([]int{2, 2, 2, 2, 1, 3, 3, 3, 3})) //1
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 18:01
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
type OnlyTwoNumberShowOnceObj struct {
|
||||
}
|
||||
|
||||
func (*OnlyTwoNumberShowOnceObj) Doc() string {
|
||||
return `
|
||||
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1)。
|
||||
`
|
||||
}
|
||||
|
||||
func OnlyTwoNumberShowOnce(numList []int) (int, int) {
|
||||
if len(numList) < 2 {
|
||||
panic("数组长度不能小于两个")
|
||||
}
|
||||
result := 0
|
||||
//先进行异或,得到异或的结果
|
||||
for _, num := range numList {
|
||||
result = result ^ num
|
||||
}
|
||||
//找到异或后为1的位置
|
||||
pos := 0
|
||||
for ; pos < 32; pos++ {
|
||||
if ((result >> pos) & 1) == 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
firstList := make([]int, 0)
|
||||
secondList := make([]int, 0)
|
||||
|
||||
//根据异或位的结果,把数组分成两组
|
||||
for _, num := range numList {
|
||||
if ((num >> pos) & 1) == 1 {
|
||||
firstList = append(firstList, num)
|
||||
} else {
|
||||
secondList = append(secondList, num)
|
||||
}
|
||||
}
|
||||
|
||||
first := 0
|
||||
for _, num := range firstList {
|
||||
first ^= num
|
||||
}
|
||||
second := 0
|
||||
|
||||
for _, num := range secondList {
|
||||
second ^= num
|
||||
}
|
||||
|
||||
return first, second
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 18:02
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberCount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOnlyTwoNumberShowOnce(t *testing.T) {
|
||||
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 1, 7})) //1,7
|
||||
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 1, 7, 8, 9, 0, 19, 19, 0, 8, 9})) //1,7
|
||||
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 1, 7, 5, 4, 3, 2})) //1,7
|
||||
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 1, 7, 1, 100})) //1,100
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 15:45
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberMoreThan
|
||||
|
||||
type NumberMoreThanHalfObj struct{}
|
||||
|
||||
func (n *NumberMoreThanHalfObj) Doc() string {
|
||||
return `
|
||||
题目:
|
||||
|
||||
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
|
||||
|
||||
例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
|
||||
|
||||
要求:时间复杂度O(N),空间复杂度O(1)
|
||||
`
|
||||
}
|
||||
|
||||
func NumberMoreThanHalf(numList []int) int {
|
||||
var number, count int
|
||||
for _, j := range numList {
|
||||
if number == j {
|
||||
count++
|
||||
} else if number != j && count <= 1 {
|
||||
number = j
|
||||
} else {
|
||||
//number !=j && count >1
|
||||
count--
|
||||
}
|
||||
}
|
||||
|
||||
//最后验证,确保一定超过
|
||||
countValid := 0
|
||||
for _, j := range numList {
|
||||
if j == number {
|
||||
countValid++
|
||||
}
|
||||
}
|
||||
if countValid <= len(numList)/2 {
|
||||
return -1
|
||||
}
|
||||
|
||||
return number
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 16:23
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberMoreThan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNumberMoreThanHalf(t *testing.T) {
|
||||
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3})) //-1
|
||||
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 1, 1})) //1
|
||||
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 1})) //-1
|
||||
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 2, 3, 2, 3, 3})) //-1
|
||||
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1})) //1
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 16:46
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberMoreThan
|
||||
|
||||
type NumberMoreThanKObj struct{}
|
||||
|
||||
func (*NumberMoreThanKObj) Doc() string {
|
||||
return `
|
||||
给定一个整型数组arr(数组长度为N) 与一个整数k,打印所有出现次数大于 N/K 的数。如果没有这样的数,返回-1。
|
||||
|
||||
要求:时间复杂度为O(N*K),额外空间复杂度为O(K)。
|
||||
`
|
||||
}
|
||||
|
||||
func NumberMoreThanK(numList []int, k int) []int {
|
||||
//小于2的情况是肯定不会超过.
|
||||
if k < 2 {
|
||||
return []int{}
|
||||
}
|
||||
|
||||
//用来保存数字与其出现次数
|
||||
numMap := make(map[int]int, 0)
|
||||
for _, num := range numList {
|
||||
//如果不存在则数值设置为1
|
||||
if _, ok := numMap[num]; !ok {
|
||||
numMap[num] = 1
|
||||
} else {
|
||||
//存在则出现次数+1
|
||||
numMap[num] = numMap[num] + 1
|
||||
}
|
||||
//当容器的大小为k
|
||||
if len(numMap) == k {
|
||||
for key, value := range numMap {
|
||||
//个数正好等于1的要删掉,因为本次减一之后,就等于0了
|
||||
if value == 1 {
|
||||
delete(numMap, key)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//map的key是可能出现次数超过N/k的数
|
||||
//这里主要是为了拿到key
|
||||
for key := range numMap {
|
||||
numMap[key] = 0
|
||||
}
|
||||
//重新计算对应数字的出现次数
|
||||
for _, num := range numList {
|
||||
if _, ok := numMap[num]; ok {
|
||||
numMap[num]++
|
||||
}
|
||||
}
|
||||
//出现次数超过k次的判断
|
||||
result := make([]int, 0)
|
||||
for key, value := range numMap {
|
||||
if value > len(numList)/k {
|
||||
result = append(result, key)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/16 16:59
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package NumberMoreThan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNumberMoreThanK(t *testing.T) {
|
||||
fmt.Println(NumberMoreThanK([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 1}, 3)) //1
|
||||
fmt.Println(NumberMoreThanK([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 1}, 4)) //1,2,3
|
||||
fmt.Println(NumberMoreThanK([]int{1, 2, 3, 1, 2, 3, 1, 2, 3}, 2)) //
|
||||
fmt.Println(NumberMoreThanK([]int{1, 2, 3}, 2)) //
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
#我的公众号二维码
|
||||

|
||||
|
||||
# 作用
|
||||
本工程仅供个人学习记录,刚开始学习go(之前是java),本工程积累一些反射的用法。后期查询更加快捷
|
||||
|
||||
@@ -60,7 +63,7 @@
|
||||
|
||||
2020/11/25:完善linq包使用示例
|
||||
|
||||
2020/12/7 :更新bit位操作工作 BitTool
|
||||
2020/12/7 : 更新bit位操作工作 BitTool
|
||||
|
||||
2020/12/15:添加前缀树工具,实现前缀搜索和字符串搜索功能
|
||||
|
||||
@@ -68,7 +71,19 @@
|
||||
|
||||
2020/12/31:新增项目案例(角色技能树)
|
||||
|
||||
2021/2/5: 新增二分查找区间内数值方法
|
||||
2021/02/05: 新增二分查找区间内数值方法
|
||||
|
||||
2021/03/02: 新增字符串匹配 暴力匹配、KMP匹配、SunDay匹配算法
|
||||
|
||||
2021/03/11: 新增Kr、Shift and/or字符串匹配算法
|
||||
|
||||
2021/03/14: 新增Manacher算法,求最长回文串
|
||||
|
||||
2021/03/18:新增超过半数数字系列算法题,新增出现次数不同的数字系列算法题
|
||||
|
||||
2021/03/26: 新增全排列的递归实现、字典序实现、递增进制位实现、递减进制位实现
|
||||
|
||||
2021/06/16 新增一个数拆分成N个数且N个数相加和等于这个数工具、测试方法
|
||||
|
||||
# 修复日志
|
||||
2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组)
|
||||
@@ -79,7 +94,13 @@
|
||||
|
||||
2020/12/31:删除源码学习部分,挪到Go-Study工程
|
||||
|
||||
2021/1/4 :reflectM包添加indirect处理指针和非指针,获取type、value
|
||||
2021/01/04:reflectM包添加indirect处理指针和非指针,获取type、value
|
||||
|
||||
2021/02/18:bitStore新增特殊档位获取方法,修改档位数目的参数标识
|
||||
|
||||
2021/02/23: 删除linq包使用示例,修改二进制工具与单测类,修改lomuto划分,修改前缀树与单测类,修改时间比较工具
|
||||
|
||||
2021/03/02: 修复Rand包随机获取方法
|
||||
|
||||
# mod vendor模式加载包
|
||||
通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到
|
||||
@@ -94,3 +115,4 @@
|
||||
- 通过 go mod vendor 切换到vendor管理
|
||||
- 在文件中import引用对应的路径
|
||||
- vendor加载对应的包
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/22 15:29
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
import (
|
||||
sort2 "Go-Tool/util/sort"
|
||||
)
|
||||
|
||||
//字典序获取全排列
|
||||
func (per *Permutation) DictionaryOrder(b []byte) {
|
||||
//先排序
|
||||
sort2.QuickSortByte(b, 0, len(b)-1)
|
||||
for {
|
||||
bef := 0
|
||||
afr := 0
|
||||
result := make([]byte, len(b))
|
||||
copy(result, b)
|
||||
per.bytes = append(per.bytes, result)
|
||||
|
||||
//从右往左找到第一个左边比右边小的数字
|
||||
for bef = len(b) - 2; ; bef-- {
|
||||
if bef < 0 {
|
||||
return
|
||||
}
|
||||
if b[bef] < b[bef+1] {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
//知道q的位置之后
|
||||
//从q开始向右边查找比位置q的数字大的第一个数字的位置
|
||||
for afr = len(b) - 1; afr > 0; afr-- {
|
||||
if b[afr] > b[bef] {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
//交换两个数字
|
||||
b[bef], b[afr] = b[afr], b[bef]
|
||||
//把后面的数字进行转置成递增顺序
|
||||
b = per.Reverse(b, bef+1, len(b)-1)
|
||||
}
|
||||
}
|
||||
|
||||
func (per *Permutation) Reverse(b []byte, start, end int) []byte {
|
||||
for start <= end {
|
||||
b[start], b[end] = b[end], b[start]
|
||||
start++
|
||||
end--
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/22 15:29
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDictionaryOrder(t *testing.T) {
|
||||
p := NewPermutation()
|
||||
|
||||
p.DictionaryOrder([]byte("1234"))
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
|
||||
p.DictionaryOrder([]byte("12345"))
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
|
||||
p.DictionaryOrder([]byte("abcde"))
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
|
||||
p.DictionaryOrder([]byte("abcdea"))
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
}
|
||||
|
||||
func TestPermutation_Reverse(t *testing.T) {
|
||||
p := NewPermutation()
|
||||
fmt.Println(p.Reverse([]byte{1, 2, 3, 4}, 0, 3))
|
||||
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5}, 0, 4))
|
||||
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5, 6}, 0, 5))
|
||||
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5, 6, 7}, 0, 6))
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/23 17:06
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
func DigitDecreases(b []int) [][]int {
|
||||
result := make([][]int, 0)
|
||||
bit := make([]int, len(b)-1)
|
||||
sum := 1
|
||||
//计算中的结果数,阶乘
|
||||
for i := 1; i <= len(b); i++ {
|
||||
sum = sum * i
|
||||
}
|
||||
for i := 0; i < sum; i++ {
|
||||
result = append(result, getRangeBySpace1(b, bit))
|
||||
bit = decreaseBit(bit)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
//根据递增进制位,并且根据【数空格法】在原来的数组中求得全排列的一种可能实现
|
||||
//origin 原始数组
|
||||
//increaseBit 递增进制位,比原始数组长度小1,这里通过数组实现,更简单
|
||||
func getRangeBySpace1(origin []int, increaseBit []int) []int {
|
||||
permutation := make([]int, len(origin))
|
||||
flag := make(map[int]bool, 0)
|
||||
//排列数组从左往右,即从大到小
|
||||
for i := 0; i < len(origin)-1; i++ {
|
||||
p := increaseBit[i] //从右到左,对应数字应该填充的位置
|
||||
j := len(origin) - 1 //该数字在本次排列的位置
|
||||
for ; ; j-- {
|
||||
//该位置未被填充
|
||||
if !flag[j] {
|
||||
p--
|
||||
}
|
||||
//找到对应位置需要推出循环
|
||||
if p < 0 {
|
||||
flag[j] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
permutation[j] = origin[i]
|
||||
}
|
||||
for i := 0; i < len(origin); i++ {
|
||||
if !flag[i] {
|
||||
permutation[i] = origin[len(origin)-1]
|
||||
}
|
||||
}
|
||||
|
||||
return permutation
|
||||
}
|
||||
|
||||
//递减进制位
|
||||
//每次加一,计算新的数组结果
|
||||
func decreaseBit(bit []int) []int {
|
||||
|
||||
//数组下标从小到大,进制位从大到小
|
||||
for i := 0; i < len(bit); i++ {
|
||||
if bit[i]+1 >= len(bit)+1-i {
|
||||
bit[i] = (bit[i] + 1) % (len(bit) + 1 - i)
|
||||
} else {
|
||||
bit[i] += 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return bit
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/23 19:53
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecreaseBit(t *testing.T) {
|
||||
|
||||
bit := []int{0, 0}
|
||||
for i := 0; i < 6; i++ {
|
||||
fmt.Println(bit)
|
||||
bit = decreaseBit(bit)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
bit = []int{0, 0, 0}
|
||||
for i := 0; i < 24; i++ {
|
||||
fmt.Println(bit)
|
||||
bit = decreaseBit(bit)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
bit = []int{0, 0, 0, 0}
|
||||
for i := 0; i < 120; i++ {
|
||||
fmt.Print(bit)
|
||||
bit = decreaseBit(bit)
|
||||
}
|
||||
|
||||
}
|
||||
func TestGetRangeBySpace1(t *testing.T) {
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{0, 0}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{1, 0}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{2, 0}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{0, 1}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{1, 1}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{2, 1}))
|
||||
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 0}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 1}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{4, 3, 2, 1}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{3, 0, 0, 0}))
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{1, 3, 2, 1}))
|
||||
|
||||
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5, 6, 7}, []int{3, 4, 2, 2, 2, 1}))
|
||||
}
|
||||
|
||||
func TestDigitDecrease(t *testing.T) {
|
||||
fmt.Println(DigitDecreases([]int{1, 2, 3}))
|
||||
fmt.Println(DigitDecreases([]int{20, 50, 30, 67}))
|
||||
fmt.Println(DigitDecreases([]int{20, 50, 30, 99, 18213}))
|
||||
fmt.Println(DigitDecreases([]int{20, 50, 30, 78321, 2321, 432}))
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/23 17:05
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
func DigitIncrease(b []int) [][]int {
|
||||
result := make([][]int, 0)
|
||||
bit := make([]int, len(b)-1)
|
||||
sum := 1
|
||||
//计算中的结果数,阶乘
|
||||
for i := 1; i <= len(b); i++ {
|
||||
sum = sum * i
|
||||
}
|
||||
for i := 0; i < sum; i++ {
|
||||
result = append(result, getRangeBySpace(b, bit))
|
||||
bit = increaseBit(bit)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
//根据递增进制位,并且根据【数空格法】在原来的数组中求得全排列的一种可能实现
|
||||
//origin 原始数组
|
||||
//increaseBit 递增进制位,比原始数组长度小1,这里通过数组实现,更简单
|
||||
func getRangeBySpace(origin []int, increaseBit []int) []int {
|
||||
permutation := make([]int, len(origin))
|
||||
flag := make(map[int]bool, 0)
|
||||
//排列数组从左往右,即从大到小
|
||||
for i := len(origin) - 1; i > 0; i-- {
|
||||
p := increaseBit[i-1] //从右到左,对应数字应该填充的位置
|
||||
j := len(origin) - 1 //该数字在本次排列的位置
|
||||
//中介数计算从左到右,即从大到小
|
||||
for ; ; j-- {
|
||||
//该位置未被填充
|
||||
if !flag[j] {
|
||||
p--
|
||||
}
|
||||
//找到对应位置需要推出循环
|
||||
if p < 0 {
|
||||
flag[j] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
permutation[j] = origin[i]
|
||||
}
|
||||
for i := 0; i < len(origin); i++ {
|
||||
if !flag[i] {
|
||||
permutation[i] = origin[0]
|
||||
}
|
||||
}
|
||||
|
||||
return permutation
|
||||
}
|
||||
|
||||
//递增进制位
|
||||
//根据递增进制位进行+1操作,返回递增的结果
|
||||
func increaseBit(bit []int) []int {
|
||||
//最开始是从二进制开始
|
||||
for i, num := range bit {
|
||||
if num+1 >= i+2 {
|
||||
bit[i] = (num + 1) % (i + 2)
|
||||
} else {
|
||||
bit[i] = num + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return bit
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/23 19:54
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetRangeBySpace(t *testing.T) {
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 0})) //123
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 0})) //
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 1})) //
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 1})) //
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 2})) //
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 2})) //321
|
||||
|
||||
//fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 0})) //12345
|
||||
//fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 1})) //21354
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4})) //54321
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 3})) //12534
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 1})) //43251
|
||||
|
||||
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5, 6, 7}, []int{1, 2, 2, 2, 4, 3})) //3647521
|
||||
}
|
||||
|
||||
func TestIncreaseBit(t *testing.T) {
|
||||
bit := []int{0, 0}
|
||||
for i := 0; i < 6; i++ {
|
||||
fmt.Println(bit)
|
||||
bit = increaseBit(bit)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
bit = []int{0, 0, 0, 0}
|
||||
for i := 0; i < 120; i++ {
|
||||
bit = increaseBit(bit)
|
||||
fmt.Println(bit)
|
||||
}
|
||||
|
||||
bit = []int{0, 0, 0}
|
||||
for i := 0; i < 24; i++ {
|
||||
bit = increaseBit(bit)
|
||||
fmt.Println(bit)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDigitIncrease(t *testing.T) {
|
||||
fmt.Println(DigitIncrease([]int{1, 2, 3}))
|
||||
fmt.Println(DigitIncrease([]int{20, 50, 30, 67}))
|
||||
fmt.Println(DigitIncrease([]int{20, 50, 30, 99, 18213}))
|
||||
fmt.Println(DigitIncrease([]int{20, 50, 30, 78321, 2321, 432}))
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/22 11:09
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
type Permutation struct {
|
||||
bytes [][]byte
|
||||
}
|
||||
|
||||
func NewPermutation() *Permutation {
|
||||
return &Permutation{
|
||||
bytes: [][]byte{},
|
||||
}
|
||||
}
|
||||
|
||||
func (per *Permutation) Recursion(b []byte, start int) {
|
||||
//递归交换到最后一个位置结束
|
||||
if start == len(b)-1 {
|
||||
bCopy := make([]byte, len(b))
|
||||
copy(bCopy, b)
|
||||
per.bytes = append(per.bytes, bCopy)
|
||||
}
|
||||
|
||||
for i := start; i < len(b); i++ {
|
||||
//交换固定位置
|
||||
b[i], b[start] = b[start], b[i]
|
||||
//固定某一个数字位置,递归后面的其他数字
|
||||
per.Recursion(b, start+1)
|
||||
//还原固定位置,进行下一次操作
|
||||
b[i], b[start] = b[start], b[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (per *Permutation) Reset() {
|
||||
per.bytes = [][]byte{}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/22 11:22
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package FullPermutation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRecursion(t *testing.T) {
|
||||
p := NewPermutation()
|
||||
|
||||
p.Recursion([]byte("123"), 0)
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
|
||||
p.Recursion([]byte("12345"), 0)
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
|
||||
p.Recursion([]byte("abcde"), 0)
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
|
||||
p.Recursion([]byte("abcdea"), 0)
|
||||
fmt.Println()
|
||||
for _, bs := range p.bytes {
|
||||
fmt.Println(string(bs))
|
||||
}
|
||||
p.Reset()
|
||||
|
||||
}
|
||||
@@ -13,7 +13,8 @@ import (
|
||||
//判断num的二进制表示某个位置是否为1
|
||||
func JudgeOneWithPosition(num int, position int) bool {
|
||||
if position < 1 {
|
||||
panic(fmt.Sprintf("输入有误:Position不能小于1,当前出入的Position为%d", position))
|
||||
panic(fmt.Sprintf("输入有误:Position不能小于1,"+
|
||||
"当前出入的Position为%d", position))
|
||||
}
|
||||
return num&(1<<uint(position-1)) != 0
|
||||
}
|
||||
@@ -30,16 +31,17 @@ func JudgeIfOdd(num int) bool {
|
||||
|
||||
//判断一个数的二进制形式是否只有一个位置为1,这个方法可以用来判断是不是2的n次方
|
||||
func JudgeOnlyOneBitWithOne(num int) bool {
|
||||
//解析:num & (num -1) 当num为2的N次方的时候, 2N次方 & (2N次方 - 1) ,因为做了最高位的右移(2N次方只有一个1,2N次方-1除了2N次方的那一个1的位置为0,其他都为1)
|
||||
//所以&的结果就是 0 ,而0 & 2N次方一定是0,所以如果结果是0,那么一定是2N次方,只有一个位置有1
|
||||
//那么 num & (num -1) 当num不是2的N次方的时候,他的结果原来有1的最高位置,一定为1,所以再和num进行 & 操作的时候,结果也一定是大于0,所以不止一个1
|
||||
return num&(num&(num-1)) == 0
|
||||
if num == 0 {
|
||||
return false
|
||||
}
|
||||
return num&(num-1) == 0
|
||||
}
|
||||
|
||||
//设置num的某一个位置为1,如果原来就是1的话,就不发生变化
|
||||
func SetOneByPosition(num int, position int) int {
|
||||
if position < 1 {
|
||||
panic(fmt.Sprintf("输入有误:Position不能小于1,当前出入的Position为%d", position))
|
||||
panic(fmt.Sprintf("输入有误:Position不能小于1,"+
|
||||
"当前出入的Position为%d", position))
|
||||
}
|
||||
return num | (1 << uint(position-1))
|
||||
}
|
||||
@@ -52,7 +54,8 @@ func JudgeWithEqualSymbol(num1 int, num2 int) bool {
|
||||
//设置某一个数num的二进制Position位为0
|
||||
func SetZeroBuPosition(num int, position int) int {
|
||||
if position < 1 {
|
||||
panic(fmt.Sprintf("输入有误:Position不能小于1,当前出入的Position为%d", position))
|
||||
panic(fmt.Sprintf("输入有误:Position不能小于1,"+
|
||||
"当前出入的Position为%d", position))
|
||||
}
|
||||
return num &^ (1 << uint(position-1))
|
||||
}
|
||||
|
||||
@@ -102,12 +102,9 @@ func TestJudgeIfEven(t *testing.T) {
|
||||
|
||||
func TestJudgeOnlyOneBitWithOne(t *testing.T) {
|
||||
fmt.Println("判断二进制表示是不是只有一个位为1")
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(1))
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(2))
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(3))
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(4))
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(56))
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(64))
|
||||
for i := 0; i <= 32; i++ {
|
||||
fmt.Println(fmt.Sprintf("%d是不是2的n次方,结果为%v", i, JudgeOnlyOneBitWithOne(i)))
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(-1))
|
||||
fmt.Println(JudgeOnlyOneBitWithOne(-2))
|
||||
|
||||
@@ -12,13 +12,13 @@ package bitStore
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
bit = 32
|
||||
realBit = 31
|
||||
bit = 32 //作为标识,没有实际作用
|
||||
realBit = 31 //真实参与计算的每个数字代表的档位数量
|
||||
)
|
||||
|
||||
type BitStore struct {
|
||||
MaxGear int //存储的最大挡位
|
||||
GearPickList []int
|
||||
MaxGear int //存储的最大挡位
|
||||
GearPickList []int //用来表示档位的数组(每一个数表示【下标 * bit】位的档位存储结果)
|
||||
}
|
||||
|
||||
//初始化方法,gear表示最大的领取档位是多少.(档位刚开始计算,没有值的情况)
|
||||
@@ -34,6 +34,19 @@ func NewBitStore(gear int, gearPickList []int) *BitStore {
|
||||
}
|
||||
}
|
||||
|
||||
//返回指定档位长度的领取状态数组
|
||||
func (bitStore *BitStore) FindSpecialGearList(gear int) []bool {
|
||||
bitStore.checkGearRight(gear) //校验传进来的长度是否正确
|
||||
bitStore.getSizeOrInit() //如果数组没有初始化,进行初始化
|
||||
return bitStore.getGearListByGear(gear) //返回指定长度的领取状态数组
|
||||
}
|
||||
|
||||
//获取当前有记录的档位的Map
|
||||
func (bitStore *BitStore) FindGearMap() map[int]bool {
|
||||
listSize := bitStore.getSizeOrInit() //获取当前数组长度,如果数组没有初始化,进行初始化
|
||||
return bitStore.shortListDeal(listSize, listSize) //短数组的处理(没有达到最大大小的数组长度)
|
||||
}
|
||||
|
||||
//获取所有档位对应的Map
|
||||
func (bitStore *BitStore) FindAllGearMap() map[int]bool {
|
||||
length := bitStore.getGearListLength(bitStore.MaxGear) //获取最大档位的长度
|
||||
@@ -60,10 +73,25 @@ func (bitStore *BitStore) ReceiveByGear(gear int) ([]int, map[int]bool) {
|
||||
bitStore.checkIfReceive(gear) //校验是否被领取了
|
||||
length := bitStore.dynamicGrowth(gear) //数组进行动态增长
|
||||
position := bitStore.getGearPosition(gear, length) //获取档位在数组中的位数位置
|
||||
bitStore.GearPickList[length-1] = bitStore.GearPickList[length-1] + (1 << uint(position))
|
||||
bitStore.GearPickList[length-1] = bitStore.GearPickList[length-1] | (1 << uint(position))
|
||||
return bitStore.GearPickList, bitStore.FindAllGearMap()
|
||||
}
|
||||
|
||||
//设置某一档位为未领取
|
||||
func (bitStore *BitStore) UnReceiveByGear(gear int) ([]int, map[int]bool) {
|
||||
bitStore.checkIfUnReceive(gear) //检验是否被领取
|
||||
length := bitStore.dynamicGrowth(gear) //数组进行动态增长
|
||||
position := bitStore.getGearPosition(gear, length) //获取档位在数组中的位数位置
|
||||
bitStore.GearPickList[length-1] = bitStore.GearPickList[length-1] - (1 << uint(position))
|
||||
return bitStore.GearPickList, bitStore.FindAllGearMap()
|
||||
}
|
||||
|
||||
func (bitStore *BitStore) checkIfUnReceive(gear int) {
|
||||
if !bitStore.IsGearReceive(gear) {
|
||||
panic("当前档位未领取,不可重置")
|
||||
}
|
||||
}
|
||||
|
||||
//判断档位是否正确
|
||||
func (bitStore *BitStore) checkGearRight(gear int) {
|
||||
if gear > bitStore.MaxGear {
|
||||
@@ -73,12 +101,12 @@ func (bitStore *BitStore) checkGearRight(gear int) {
|
||||
|
||||
//获取当前档位对应的数组长度(这边的length是从1开始的.)
|
||||
func (bitStore *BitStore) getGearListLength(gear int) int {
|
||||
return ((gear - 1) + (bit - 1)) / (bit - 1)
|
||||
return ((gear - 1) + realBit) / realBit
|
||||
}
|
||||
|
||||
//获取档位所在的二进制位置
|
||||
func (bitStore *BitStore) getGearPosition(gear, length int) int {
|
||||
return (gear - 1) % (bit - 1)
|
||||
return (gear - 1) - realBit*(length-1)
|
||||
}
|
||||
|
||||
func (bitStore *BitStore) getSizeOrInit() int {
|
||||
@@ -91,8 +119,8 @@ func (bitStore *BitStore) getSizeOrInit() int {
|
||||
func (bitStore *BitStore) fullListDeal(listSize int, length int) map[int]bool {
|
||||
resultMap := make(map[int]bool, 0)
|
||||
for i := 0; i < length; i++ {
|
||||
for j := 0; j < bit-1 && bitStore.MaxGear > i*(bit-1)+j; j++ {
|
||||
resultMap[i*(bit-1)+j+1] = (bitStore.GearPickList[i] & (1 << uint(j))) > 0
|
||||
for j := 0; j < realBit && bitStore.MaxGear > i*realBit+j; j++ {
|
||||
resultMap[i*realBit+j+1] = (bitStore.GearPickList[i] & (1 << uint(j))) > 0
|
||||
}
|
||||
}
|
||||
return resultMap
|
||||
@@ -101,13 +129,14 @@ func (bitStore *BitStore) fullListDeal(listSize int, length int) map[int]bool {
|
||||
func (bitStore *BitStore) shortListDeal(listSize, length int) map[int]bool {
|
||||
resultMap := make(map[int]bool, 0)
|
||||
for i := 0; i < listSize; i++ {
|
||||
for j := 0; j < (bit - 1); j++ {
|
||||
resultMap[i*(bit-1)+j+1] = (bitStore.GearPickList[i] & (1 << uint(j))) > 0
|
||||
for j := 0; j < realBit; j++ {
|
||||
resultMap[i*realBit+j+1] =
|
||||
(bitStore.GearPickList[i] & (1 << uint(j))) > 0
|
||||
}
|
||||
}
|
||||
for i := listSize; i < length; i++ {
|
||||
for j := 0; j < (bit-1) && bitStore.MaxGear > i*(bit-1)+j; j++ {
|
||||
resultMap[i*(bit-1)+j+1] = false
|
||||
for j := 0; j < realBit && bitStore.MaxGear > i*realBit+j; j++ {
|
||||
resultMap[i*realBit+j+1] = false
|
||||
}
|
||||
}
|
||||
return resultMap
|
||||
@@ -131,3 +160,29 @@ func (bitStore *BitStore) checkIfReceive(gear int) {
|
||||
panic("当前档位已被领取,不可重复领取")
|
||||
}
|
||||
}
|
||||
|
||||
func (bitStore *BitStore) getGearListByGear(gear int) []bool {
|
||||
gearList := make([]bool, 0)
|
||||
listAllGear := len(bitStore.GearPickList) * realBit //当前已领取数组可表示的总档位
|
||||
//如果指定的长度大于gear已有数组长度,需要特殊处理
|
||||
if listAllGear <= gear {
|
||||
for i := 0; i < (listAllGear-1)/realBit+1; i++ {
|
||||
for j := 0; j < realBit && realBit*i+j < gear; j++ {
|
||||
gearList = append(gearList, (bitStore.GearPickList[i]&(1<<uint(j))) > 0)
|
||||
}
|
||||
}
|
||||
for i := 0; i < gear-listAllGear; i++ {
|
||||
for j := 0; j < realBit && realBit*i+j < gear-listAllGear; j++ {
|
||||
gearList = append(gearList, false)
|
||||
}
|
||||
}
|
||||
return gearList
|
||||
}
|
||||
//如果获取的档位比实际记录的档位小
|
||||
for i := 0; i < (gear-1)/realBit+1; i++ {
|
||||
for j := 0; j < realBit && realBit*i+j < gear; j++ {
|
||||
gearList = append(gearList, (bitStore.GearPickList[i]&(1<<uint(j))) > 0)
|
||||
}
|
||||
}
|
||||
return gearList
|
||||
}
|
||||
|
||||
@@ -7,12 +7,74 @@
|
||||
package bitStore
|
||||
|
||||
import (
|
||||
"Go-Tool/util/sort"
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBitStore(t *testing.T) {
|
||||
fmt.Println("测试2档的情况")
|
||||
testTwo()
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("测试10档的情况")
|
||||
testTen()
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("测试18档的情况")
|
||||
testEighteen()
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("测试33档的情况")
|
||||
testThirtyThree()
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("测试58档的情况")
|
||||
testFiftyEight()
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("测试1000档的情况")
|
||||
testOneThousand(t)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func TestBitStoreFind(t *testing.T) {
|
||||
bitStore := NewBitStore(120, nil)
|
||||
bitStore.ReceiveByGear(1)
|
||||
bitStore.ReceiveByGear(3)
|
||||
bitStore.ReceiveByGear(5)
|
||||
bitStore.ReceiveByGear(7)
|
||||
bitStore.ReceiveByGear(13)
|
||||
bitStore.ReceiveByGear(10)
|
||||
bitStore.ReceiveByGear(16)
|
||||
bitStore.ReceiveByGear(33)
|
||||
bitStore.ReceiveByGear(35)
|
||||
|
||||
fmt.Println(bitStore.FindGearMap())
|
||||
fmt.Println(bitStore.FindSpecialGearList(1))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(1)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(4))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(4)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(2))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(2)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(10))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(10)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(13))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(13)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(14))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(14)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(20))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(20)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(32))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(32)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(63))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(63)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(64))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(64)))
|
||||
fmt.Println(bitStore.FindSpecialGearList(65))
|
||||
fmt.Println(len(bitStore.FindSpecialGearList(65)))
|
||||
}
|
||||
|
||||
func newStoreMap(bitStore *BitStore) {
|
||||
gearMap := bitStore.FindAllGearMap()
|
||||
falseList := make([]int, 0)
|
||||
@@ -34,22 +96,21 @@ func getReceiveResult(bitStore *BitStore) {
|
||||
keyList = append(keyList, key)
|
||||
}
|
||||
}
|
||||
sort.BubbleSort(keyList)
|
||||
fmt.Println("已经领取的档位信息如下")
|
||||
for value := range keyList {
|
||||
fmt.Print(fmt.Sprintf("%d,", keyList[value]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOneThousand(t *testing.T) {
|
||||
func testOneThousand(t *testing.T) {
|
||||
bitStore := NewBitStore(1000, nil)
|
||||
|
||||
newStoreMap(bitStore) //初始化的校验
|
||||
|
||||
fmt.Println()
|
||||
bitStore.ReceiveByGear(1)
|
||||
bitStore.ReceiveByGear(3)
|
||||
fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[0]))
|
||||
fmt.Println(fmt.Sprintf("这个时候领取结果 1应该返回true,结果是:%v", bitStore.IsGearReceive(3)))
|
||||
fmt.Println(fmt.Sprintf("这个时候领取结果 3应该返回true,结果是:%v", bitStore.IsGearReceive(3)))
|
||||
bitStore.ReceiveByGear(8)
|
||||
fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[0]))
|
||||
fmt.Println(fmt.Sprintf("这个时候领取结果 8应该返回true,结果是:%v", bitStore.IsGearReceive(8)))
|
||||
@@ -76,10 +137,10 @@ func TestOneThousand(t *testing.T) {
|
||||
fmt.Println(fmt.Sprintf("这个时候领取结果 44应该返回true,结果是:%v", bitStore.IsGearReceive(44)))
|
||||
bitStore.ReceiveByGear(48)
|
||||
fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[1]))
|
||||
fmt.Println(fmt.Sprintf("这个时候领取结果 48应该返回true,结果是:%v", bitStore.IsGearReceive(48)))
|
||||
|
||||
fmt.Println(fmt.Sprintf("判断当前数组是否动态增长,当前数组长度为:%d", len(bitStore.GearPickList)))
|
||||
|
||||
fmt.Println(fmt.Sprintf("这个时候领取结果 48应该返回true,结果是:%v", bitStore.IsGearReceive(48)))
|
||||
bitStore.ReceiveByGear(123)
|
||||
fmt.Println(fmt.Sprintf("这个时候领取结果 123应该返回true,结果是:%v", bitStore.IsGearReceive(123)))
|
||||
|
||||
@@ -100,7 +161,7 @@ func TestOneThousand(t *testing.T) {
|
||||
getReceiveResult(bitStore)
|
||||
}
|
||||
|
||||
func TestFiftyEight(t *testing.T) {
|
||||
func testFiftyEight() {
|
||||
bitStore := NewBitStore(58, nil)
|
||||
|
||||
newStoreMap(bitStore) //初始化的校验
|
||||
@@ -133,7 +194,7 @@ func TestFiftyEight(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestThirtyThree(t *testing.T) {
|
||||
func testThirtyThree() {
|
||||
bitStore := NewBitStore(33, nil)
|
||||
|
||||
newStoreMap(bitStore) //初始化的校验
|
||||
@@ -160,7 +221,7 @@ func TestThirtyThree(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEighteen(t *testing.T) {
|
||||
func testEighteen() {
|
||||
bitStore := NewBitStore(18, nil)
|
||||
|
||||
newStoreMap(bitStore) //初始化的校验
|
||||
@@ -181,7 +242,7 @@ func TestEighteen(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTen(t *testing.T) {
|
||||
func testTen() {
|
||||
bitStore := NewBitStore(10, nil)
|
||||
|
||||
newStoreMap(bitStore) //初始化的校验
|
||||
@@ -200,7 +261,7 @@ func TestTen(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTwo(t *testing.T) {
|
||||
func testTwo() {
|
||||
bitStore := NewBitStore(2, nil)
|
||||
|
||||
newStoreMap(bitStore) //初始化的校验
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/11/12 14:04
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package linqUse
|
||||
|
||||
import "time"
|
||||
|
||||
type Book struct {
|
||||
Name string
|
||||
Author string
|
||||
Money float64
|
||||
WordsNum int
|
||||
PublishTime time.Time
|
||||
}
|
||||
|
||||
func MakeBook() []Book {
|
||||
bookList := make([]Book, 0)
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Go语言",
|
||||
Author: "Go",
|
||||
Money: 100,
|
||||
WordsNum: 1000,
|
||||
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Effective Java",
|
||||
Author: "Java",
|
||||
Money: 78,
|
||||
WordsNum: 9000,
|
||||
PublishTime: time.Date(2020, 2, 15, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Java语言",
|
||||
Author: "Java",
|
||||
Money: 50,
|
||||
WordsNum: 3000,
|
||||
PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Lua语言",
|
||||
Author: "Lua",
|
||||
Money: 75,
|
||||
WordsNum: 45000,
|
||||
PublishTime: time.Date(2020, 1, 10, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "React语言",
|
||||
Author: "React",
|
||||
Money: 99,
|
||||
WordsNum: 14500,
|
||||
PublishTime: time.Date(2020, 7, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Red语言",
|
||||
Author: "Red",
|
||||
Money: 28,
|
||||
WordsNum: 880,
|
||||
PublishTime: time.Date(2019, 4, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "JavaScript语言",
|
||||
Author: "JavaScript",
|
||||
Money: 81,
|
||||
WordsNum: 3776,
|
||||
PublishTime: time.Date(2019, 5, 17, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
return bookList
|
||||
}
|
||||
|
||||
func MakeBook1() []Book {
|
||||
bookList := make([]Book, 0)
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Go语言",
|
||||
Author: "Go",
|
||||
Money: 100,
|
||||
WordsNum: 1000,
|
||||
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Effective Java",
|
||||
Author: "Java",
|
||||
Money: 78,
|
||||
WordsNum: 9000,
|
||||
PublishTime: time.Date(2020, 2, 15, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Go语言(第二版)",
|
||||
Author: "Go",
|
||||
Money: 50,
|
||||
WordsNum: 3000,
|
||||
PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
return bookList
|
||||
}
|
||||
func MakeBook2() []Book {
|
||||
bookList := make([]Book, 0)
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Go语言",
|
||||
Author: "Go",
|
||||
Money: 100,
|
||||
WordsNum: 1000,
|
||||
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
return bookList
|
||||
}
|
||||
|
||||
func MakeBook3() []Book {
|
||||
bookList := make([]Book, 0)
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Go语言",
|
||||
Author: "Go",
|
||||
Money: 100,
|
||||
WordsNum: 1000,
|
||||
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList = append(bookList, Book{
|
||||
Name: "Go语言(第三版)",
|
||||
Author: "Go",
|
||||
Money: 50,
|
||||
WordsNum: 3000,
|
||||
PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
return bookList
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/11/24 16:17
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package linqUse
|
||||
|
||||
type Person struct {
|
||||
Name string //拥有者的名字
|
||||
}
|
||||
|
||||
type Pet struct {
|
||||
Name string //动物的名字
|
||||
OwnerName string //拥有者的名字
|
||||
}
|
||||
|
||||
type Man struct {
|
||||
Name string //拥有者的名字
|
||||
Pets []Pets //宠物们
|
||||
}
|
||||
|
||||
type Pets struct {
|
||||
Name string //动物的名字
|
||||
}
|
||||
|
||||
func MakeInnerData() []Man {
|
||||
man := make([]Man, 0)
|
||||
man = append(man, Man{
|
||||
Name: "康康",
|
||||
Pets: []Pets{{Name: "康康的狗"}, {Name: "康康的猫"}},
|
||||
})
|
||||
man = append(man, Man{
|
||||
Name: "老施",
|
||||
Pets: []Pets{{Name: "老施的🐟"}, {Name: "老施的鸟"}},
|
||||
})
|
||||
man = append(man, Man{
|
||||
Name: "小明",
|
||||
Pets: []Pets{{Name: "小明的🐖"}, {Name: "小明的狗"}},
|
||||
})
|
||||
|
||||
return man
|
||||
}
|
||||
|
||||
func MakeJoinData() ([]Person, []Pet) {
|
||||
kangkang := Person{Name: "爱吃合合乐的康康"}
|
||||
laoshi := Person{Name: "老施"}
|
||||
xiaoming := Person{Name: "不要催-小明"}
|
||||
expect := Person{Name: "我是没有宠物的人"}
|
||||
|
||||
dog := Pet{Name: "康康的狗", OwnerName: kangkang.Name}
|
||||
cat := Pet{Name: "康康的猫", OwnerName: kangkang.Name}
|
||||
fish := Pet{Name: "老施的🐟", OwnerName: laoshi.Name}
|
||||
pig := Pet{Name: "小明的🐖", OwnerName: xiaoming.Name}
|
||||
|
||||
return []Person{kangkang, laoshi, xiaoming, expect}, []Pet{dog, cat, fish, pig}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/11/12 14:43
|
||||
* @Description:测试方法集合
|
||||
*/
|
||||
|
||||
package linqUse
|
||||
|
||||
import "time"
|
||||
|
||||
//书籍发布时间是否早于--.--.--
|
||||
var PublishTimeBeforeFunc = func(thisBook interface{}) bool {
|
||||
if thisBook.(Book).PublishTime.Before(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//书籍发布时间是否晚于--.--.--
|
||||
var PublishTimeAfterFunc = func(thisBook interface{}) bool {
|
||||
if thisBook.(Book).PublishTime.After(time.Date(2018, 1, 1, 0, 0, 0, 0, time.Local)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//书籍发布时间是否晚于--.--.--
|
||||
var PublishTimeAfterFunc2 = func(thisBook interface{}) bool {
|
||||
if thisBook.(Book).PublishTime.After(time.Date(2021, 1, 1, 0, 0, 0, 0, time.Local)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//自定义聚合操作方法
|
||||
var AggregateFunc = func(first interface{}, second interface{}) interface{} {
|
||||
if first.(Book).PublishTime.Before(second.(Book).PublishTime) {
|
||||
return first
|
||||
}
|
||||
return second
|
||||
}
|
||||
@@ -1,531 +0,0 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/11/12 10:52
|
||||
* @Description:这边是linq包的使用操作,为之后的使用做一些示例
|
||||
* 包引用命令: go get github.com/ahmetb/go-linq
|
||||
* 示例参考地址:https://godoc.org/github.com/ahmetb/go-linq#
|
||||
* 在Idea中对应方法名上使用 Shift+F1 组合键操作可以直接跳转到方法对应的地址
|
||||
*/
|
||||
|
||||
package linqUse
|
||||
|
||||
import (
|
||||
"Go-Tool/util/timed"
|
||||
"fmt"
|
||||
"github.com/ahmetb/go-linq"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
||||
Aggregate() //自定义聚合操作
|
||||
|
||||
All() //判断数组的所有元素是否都满足条件
|
||||
|
||||
Where() //根据条件查询对应的元素
|
||||
|
||||
AnyWith() //判断数组是否有任意个元素满足条件
|
||||
|
||||
Calculate() //这个方法只能计算数值类型
|
||||
|
||||
Combine() //组合两个数组的两种方式
|
||||
|
||||
Contains() //包含
|
||||
|
||||
FirstAndLast() //第一个和最后一个
|
||||
|
||||
Distinct() //返回数组中唯一的元素
|
||||
|
||||
Except() //返回第一个序列没有出现在第二个序列中的成员
|
||||
|
||||
GroupBy() //按照对应规则进行分组
|
||||
|
||||
Intersect() //产生两个数组的交集
|
||||
|
||||
OrderBy() //排序
|
||||
|
||||
Skip() //略过指定条件的元素
|
||||
|
||||
Count() //计算数组总长度
|
||||
|
||||
Result() //对结果集进行操作
|
||||
|
||||
Take() //获取对应数量的元素,一般多用在排序后前几个的元素
|
||||
|
||||
Select() //筛选结构体中对应的元素
|
||||
|
||||
SelectMany() //对多维数组进行合并或者其他处理 对结构体中的数组进行处理(与结构体结合操作)
|
||||
|
||||
Join() //对两个有关联的数据进行处理
|
||||
|
||||
}
|
||||
|
||||
func Where() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
query.WhereT(func(book Book) bool {
|
||||
return book.Money > float64(70)
|
||||
}).ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
|
||||
})
|
||||
}
|
||||
|
||||
func Take() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
query.OrderByDescendingT(func(book Book) string {
|
||||
return book.Author
|
||||
}).Take(3).ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
|
||||
//超出对应数量的元素会不会报错(输出所有的元素)
|
||||
query.OrderByDescendingT(func(book Book) string {
|
||||
return book.Author
|
||||
}).Take(100).ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
//负数会发生什么情况(直接返回,不做操作)
|
||||
query.OrderByDescendingT(func(book Book) string {
|
||||
return book.Author
|
||||
}).Take(-2).ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
|
||||
})
|
||||
|
||||
//TakeWhile系列的方法,虽然能够根据条件进行查询,但是有一个弊端就是一旦查询到的结果和条件不符合则直接返回,也就是说后面满足条件的元素不会再被做筛选
|
||||
//那么比如这边的这个大于的操作,就需要对整个数组进行排序之后然后进行筛选,如果不希望排序,则用原生的for循环可能会更好
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
query.TakeWhileT(func(book Book) bool {
|
||||
return book.Money > float64(70)
|
||||
}).ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
|
||||
})
|
||||
}
|
||||
|
||||
func Result() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
|
||||
bookMap := make(map[string]string, 0)
|
||||
query.SelectT(func(book Book) linq.KeyValue {
|
||||
return linq.KeyValue{
|
||||
Key: book.Author,
|
||||
Value: book.Name,
|
||||
}
|
||||
}).ToMap(&bookMap)
|
||||
|
||||
for key, value := range bookMap {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", key, value))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
|
||||
//如果key相同的话,前面的元素会被覆盖掉(只会保留最后一个)
|
||||
bookList1 := MakeBook1()
|
||||
query1 := linq.From(bookList1)
|
||||
bookMap1 := make(map[string]string, 0)
|
||||
query1.SelectT(func(book Book) linq.KeyValue {
|
||||
return linq.KeyValue{
|
||||
Key: book.Author,
|
||||
Value: book.Name,
|
||||
}
|
||||
}).ToMap(&bookMap1)
|
||||
|
||||
for key, value := range bookMap1 {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", key, value))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
bookList2 := MakeBook()
|
||||
query2 := linq.From(bookList2)
|
||||
|
||||
bookMap2 := make(map[string]Book, 0)
|
||||
query2.ToMapByT(&bookMap2,
|
||||
//这个方法决定key的字段是什么
|
||||
func(book Book) string {
|
||||
return book.Author
|
||||
}, //这个方法决定value的字段是什么
|
||||
func(book Book) Book {
|
||||
return book
|
||||
})
|
||||
|
||||
for key, value := range bookMap2 {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", key, value.Name))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
bookListResult := make([]Book, 0)
|
||||
linq.From(MakeBook()).OrderByDescendingT(func(book Book) string {
|
||||
return book.Author
|
||||
}).ToSlice(&bookListResult)
|
||||
for _, value := range bookListResult {
|
||||
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", value.Author, value.Name))
|
||||
}
|
||||
}
|
||||
|
||||
func Count() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
fmt.Println(fmt.Sprintf("数组中发布时间早于2019-1-1的书有%d本", query.CountWithT(PublishTimeBeforeFunc)))
|
||||
fmt.Println(fmt.Sprintf("数组中发布时间晚于2018-1-1的书有%d本", query.CountWithT(PublishTimeAfterFunc)))
|
||||
}
|
||||
|
||||
func Skip() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
|
||||
fmt.Println(fmt.Sprintf("跳过三个元素,返回的数组中包含%d个元素", len(query.Skip(3).Results())))
|
||||
fmt.Println(fmt.Sprintf("跳过发布时间在2018.1.1之后的元素,返回的数组中包含%d个元素", query.SkipWhile(PublishTimeAfterFunc).Count()))
|
||||
}
|
||||
|
||||
func SelectMany() {
|
||||
input := [][]int{{1, 2, 3}, {4, 5, 6, 7}}
|
||||
|
||||
//二位数组进行合并
|
||||
linq.From(input).SelectManyT(
|
||||
func(i []int) linq.Query {
|
||||
return linq.From(i)
|
||||
},
|
||||
).ForEachT(func(num int) {
|
||||
fmt.Println(num)
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
|
||||
//三维数组进行合并
|
||||
input1 := [][][]int{{{1, 2, 3}}, {{4, 5, 6, 7}, {8, 9, 10}}}
|
||||
linq.From(input1).SelectManyT(
|
||||
func(i [][]int) linq.Query {
|
||||
return linq.From(i)
|
||||
},
|
||||
).SelectManyT(
|
||||
func(i []int) linq.Query {
|
||||
return linq.From(i)
|
||||
},
|
||||
).ForEachT(func(num int) {
|
||||
fmt.Print(num)
|
||||
fmt.Print(" ")
|
||||
})
|
||||
|
||||
//SelectMany的主要作用是,结构体中包含数组元素,可以把数组元素取出来和结构体做相应的操作
|
||||
//如果是结构体中有多个数组的操作,可以把对应的多个数组放到一个新定义的结构体数组中
|
||||
fmt.Println()
|
||||
men := MakeInnerData()
|
||||
linq.From(men).
|
||||
//第一个方法筛选出结构体对应的数组
|
||||
SelectManyByT(func(man Man) linq.Query {
|
||||
return linq.From(man.Pets)
|
||||
},
|
||||
//第二个方法这边可以拿到数组中元素对应的结构体的数据.
|
||||
func(pet Pets, man Man) map[string]Pets {
|
||||
return map[string]Pets{
|
||||
man.Name: pet,
|
||||
}
|
||||
}).ForEachT(func(petWithMan map[string]Pets) {
|
||||
for key, value := range petWithMan {
|
||||
fmt.Println(fmt.Sprintf("%v拥有一只宠物,它的名字叫做%v", key, value.Name))
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func Select() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
|
||||
//筛选出结构体对应的元素
|
||||
query.SelectT(func(book Book) string {
|
||||
return book.Name
|
||||
}).ForEachT(func(bookName string) {
|
||||
fmt.Println(fmt.Sprintf("书名%v", bookName))
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
|
||||
//根据下标进行返回,如果是跟下标有关的,则可以通过这个方法进行组合然后返回.
|
||||
query.SelectIndexedT(func(index int, book Book) []string {
|
||||
return []string{strconv.Itoa(index + 1), book.Name}
|
||||
}).ForEachT(func(book []string) {
|
||||
fmt.Println(fmt.Sprintf("第%v本书,书名%v", book[0], book[1]))
|
||||
})
|
||||
}
|
||||
|
||||
//OrderBy可以按照对应的规则进行排序,可以实现多重排序,需要注意的就是OrderBy是从到达,orderByDescending是从大到小
|
||||
func OrderBy() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
query = query.OrderByDescendingT(func(book Book) string {
|
||||
return book.Name
|
||||
}).ThenByDescendingT(func(book Book) string {
|
||||
return book.Author
|
||||
}).ThenByDescendingT(func(book Book) float64 {
|
||||
return book.Money
|
||||
}).Query
|
||||
|
||||
query.ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
|
||||
//reverse: 把结果逆序
|
||||
query.Reverse().ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
}
|
||||
|
||||
func Join() {
|
||||
//任务和动物有关联,直接找到对应的关系,没有对应关系的数据不会处理,正常情况下应该用更单一的数据来做关联
|
||||
persons, pets := MakeJoinData()
|
||||
query1 := linq.From(persons)
|
||||
query2 := linq.From(pets)
|
||||
query1.JoinT(query2,
|
||||
func(person Person) string {
|
||||
return person.Name
|
||||
},
|
||||
func(pet Pet) string {
|
||||
return pet.OwnerName
|
||||
},
|
||||
func(person Person, pet Pet) map[string]Pet {
|
||||
petMap := make(map[string]Pet)
|
||||
petMap[person.Name] = pet
|
||||
return petMap
|
||||
},
|
||||
).ForEachT(func(petMap map[string]Pet) {
|
||||
for key, value := range petMap {
|
||||
fmt.Println(fmt.Sprintf("%v拥有一只宠物,它的名字叫做:%v", key, value.Name))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Intersect() {
|
||||
bookList1 := MakeBook1()
|
||||
query1 := linq.From(bookList1)
|
||||
bookList2 := MakeBook2()
|
||||
query2 := linq.From(bookList2)
|
||||
|
||||
fmt.Println("输出对应的书籍元素,按照结构体判断交集")
|
||||
query3 := query1.Intersect(query2)
|
||||
query3.ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("输出对应的书籍元素,按照元素判断交集")
|
||||
query3 = query1.IntersectByT(query2, func(book Book) string {
|
||||
return book.Author
|
||||
})
|
||||
query3.ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
|
||||
//这边计算是按照结构体的一个元素进行比较。事实证明无论是否按照结构体的元素筛选,返回的都是完全相同的元素
|
||||
fmt.Println()
|
||||
fmt.Println("输出对应的书籍元素,按照元素判断交集2")
|
||||
bookList1 = MakeBook1()
|
||||
query1 = linq.From(bookList1)
|
||||
bookList3 := MakeBook3()
|
||||
query2 = linq.From(bookList3)
|
||||
query3 = query2.IntersectByT(query1, func(book Book) string {
|
||||
return book.Author
|
||||
})
|
||||
query3.ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("判断是否会不重复的处理")
|
||||
query1 = linq.From([]int{1, 2, 3, 4, 5, 3})
|
||||
query2 = linq.From([]int{1, 3, 3, 78, 99, 0, 111})
|
||||
query3 = query2.IntersectByT(query1, func(i int) int {
|
||||
return i
|
||||
})
|
||||
fmt.Println(query3.Results())
|
||||
}
|
||||
|
||||
func GroupBy() {
|
||||
bookList1 := MakeBook1()
|
||||
query := linq.From(bookList1)
|
||||
|
||||
fmt.Println("输出对应书名和作者")
|
||||
//第一个func是分组的依据,第二个func是分组后返回的元素.
|
||||
query = query.GroupByT(func(book Book) string {
|
||||
return book.Author
|
||||
}, func(book Book) Book {
|
||||
return book
|
||||
})
|
||||
|
||||
query.ForEachT(func(bookGroup linq.Group) {
|
||||
fmt.Println(fmt.Sprintf("作者是%v", bookGroup.Key))
|
||||
for _, item := range bookGroup.Group {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", item.(Book).Name, item.(Book).Author))
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
})
|
||||
fmt.Println()
|
||||
fmt.Println("输出对应书名")
|
||||
|
||||
bookList1 = MakeBook1()
|
||||
query = linq.From(bookList1)
|
||||
var nameGroups []linq.Group
|
||||
query.GroupByT(
|
||||
func(book Book) string { return book.Author },
|
||||
func(book Book) string { return book.Name },
|
||||
).ToSlice(&nameGroups)
|
||||
|
||||
for _, item := range nameGroups {
|
||||
fmt.Println(fmt.Sprintf("作者是%v", item.Key))
|
||||
for _, row := range item.Group {
|
||||
fmt.Println(fmt.Sprintf("书名%v", row))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Except() {
|
||||
bookList1 := MakeBook1()
|
||||
query1 := linq.From(bookList1)
|
||||
bookList2 := MakeBook2()
|
||||
query2 := linq.From(bookList2)
|
||||
|
||||
fmt.Println("输出对应书名和作者")
|
||||
//判断结构结构体本身是否相等
|
||||
query1.Except(query2).
|
||||
ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("输出对应书名和作者")
|
||||
//判断结构体的某个字段是否出现
|
||||
query1.ExceptByT(query2, func(book Book) string {
|
||||
return book.Author
|
||||
}).ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
}
|
||||
|
||||
func Distinct() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
query = query.Append(Book{
|
||||
Name: "Go语言",
|
||||
Author: "Go",
|
||||
Money: 100,
|
||||
WordsNum: 1000,
|
||||
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
bookList1 := make([]Book, 0)
|
||||
query.ToSlice(&bookList1)
|
||||
fmt.Println(fmt.Sprintf("筛选之前query中总共有%d个数据", query.Count()))
|
||||
//这边的distinct如果是结构体,则判断的是结构体的所有值,如果是指针则判断的是指针地址.
|
||||
query = query.Distinct()
|
||||
fmt.Println(fmt.Sprintf("筛选之后query中总共有%d个数据", query.Count()))
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("输出对应书名和作者")
|
||||
query = query.Append(Book{
|
||||
Name: "Go语言(第二版)",
|
||||
Author: "Go",
|
||||
Money: 100,
|
||||
WordsNum: 1000,
|
||||
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
|
||||
})
|
||||
//根据对应的规则来判断是否相同 -- 如果对应的字段一样,只会保留第一个找到的,后面的会被清除掉
|
||||
query.DistinctByT(func(book Book) string {
|
||||
return book.Author
|
||||
}).ForEachT(func(book Book) {
|
||||
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
|
||||
})
|
||||
}
|
||||
|
||||
func Combine() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
query1 := query.Concat(query) //不会排除重复项
|
||||
query2 := query.Union(query) //会排除重复项
|
||||
fmt.Println(fmt.Sprintf("不会排除重复项的方法返回的元素个数是%d", len(query1.Results())))
|
||||
fmt.Println(fmt.Sprintf("会排除重复项的方法返回的元素个数是%d", len(query2.Results())))
|
||||
query1 = query1.Append(Book{Name: "Last One"}) //加在原来的Query的最后面
|
||||
query2 = query2.Prepend(Book{Name: "First One"}) //加在原来的Query的第一个
|
||||
fmt.Println(fmt.Sprintf("最后一个元素是%v", query1.Last()))
|
||||
fmt.Println(fmt.Sprintf("第一个元素是%v", query2.First()))
|
||||
}
|
||||
|
||||
func FirstAndLast() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
fmt.Println(fmt.Sprintf("数组第一本书书名叫:%s", query.First().(Book).Name))
|
||||
fmt.Println(fmt.Sprintf("数组第一本书发布时间在2018年1月1号之后的书书名叫:%s", query.FirstWith(PublishTimeAfterFunc).(Book).Name))
|
||||
|
||||
fmt.Println(fmt.Sprintf("数组最后一本书书名叫:%s", query.Last().(Book).Name))
|
||||
fmt.Println(fmt.Sprintf("数组最后一本书发布时间在2018年1月1号之后的书书名叫:%s", query.LastWith(PublishTimeAfterFunc).(Book).Name))
|
||||
}
|
||||
|
||||
func Contains() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
//这边需要注意是的是如果要判断两个元素是否相等,在go里面不能使用元素的地址
|
||||
// 所以这边加到query里面的必须不能是元素的地址,否则没办法比较结构体本身,而是比较结构体的地址
|
||||
fmt.Println(fmt.Sprintf("判断当前数组是否包含相同的元素,判断的是所有的值,而不是地址,结果是%v", query.Contains(Book{
|
||||
Name: "Go语言",
|
||||
Author: "Go",
|
||||
Money: 100,
|
||||
WordsNum: 1000,
|
||||
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
|
||||
})))
|
||||
}
|
||||
|
||||
func Calculate() {
|
||||
query := linq.From([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
fmt.Println(fmt.Sprintf("平均值为:%f", query.Average()))
|
||||
fmt.Println(fmt.Sprintf("最大的值为%d", query.Max()))
|
||||
fmt.Println(fmt.Sprintf("最小的值为%d", query.Min()))
|
||||
}
|
||||
|
||||
func AnyWith() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
result := query.AnyWith(PublishTimeBeforeFunc) //判断是否有任意个元素满足条件
|
||||
fmt.Println(fmt.Sprintf("是否有任意书的发表时间早于2020年1月1号,答案是%v", result))
|
||||
|
||||
result = query.AnyWith(PublishTimeAfterFunc2) //判断是否有任意个元素满足条件
|
||||
fmt.Println(fmt.Sprintf("是否有任意书的发表时间晚于2021年1月1号,答案是%v", result))
|
||||
}
|
||||
|
||||
func All() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
result := query.All(PublishTimeBeforeFunc)
|
||||
fmt.Println(fmt.Sprintf("是否所有的书的发表时间都早于2020年1月1号,答案是%v", result))
|
||||
|
||||
result = query.All(PublishTimeAfterFunc)
|
||||
fmt.Println(fmt.Sprintf("是否所有的书的发表时间都晚于2018年1月1号,答案是%v", result))
|
||||
}
|
||||
|
||||
func Aggregate() {
|
||||
bookList := MakeBook()
|
||||
query := linq.From(bookList)
|
||||
// 这边的聚合操作其实就是【自定义对应的比较方法】。
|
||||
// 根据注释,第一次拿到的是数组的第一个元素,然后跟第二个元素进行比较,如果第二个元素符合条件则【替换第一个元素】,否则当前聚合操作还是持有第一个元素。
|
||||
// 以此类推后面的元素
|
||||
result := query.Aggregate(AggregateFunc).(Book)
|
||||
fmt.Println(fmt.Sprintf("聚合操作查询出的结果是【%s】这本书,它的发布时间最早为:%v", result.Name, timed.GetTimeDefaultFormatString(result.PublishTime.Unix())))
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/13 21:58
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package palindrome
|
||||
|
||||
import "fmt"
|
||||
|
||||
//返回字符串中最大回文的数量和回文字符串
|
||||
func Manacher(allString string) (int, string) {
|
||||
maxMid := 0 //当前最大回文串中部下标
|
||||
radiusPos := 0 //最大回文半径对应的右边的下标位置
|
||||
result := generateString(allString)
|
||||
point := make([]int, len(result)) //以j为中心的最长回文半径
|
||||
maxLen := -1
|
||||
var palindrome string
|
||||
|
||||
for i := 1; i < len(result); i++ {
|
||||
j := 2*maxMid - i //与i下标对称的左边的下标
|
||||
if i >= radiusPos {
|
||||
point[i] = 1
|
||||
} else if radiusPos-i > point[j] {
|
||||
point[i] = point[j]
|
||||
} else {
|
||||
// point[j] >= radiusPos-i
|
||||
point[i] = radiusPos - i
|
||||
}
|
||||
//从后面的位置继续开始找对应的字符
|
||||
for (i-point[i] >= 0 && i+point[i] < len(result)) && result[i+point[i]] == result[i-point[i]] {
|
||||
point[i]++
|
||||
}
|
||||
//更新最长回文串信息
|
||||
if i+point[i] > radiusPos {
|
||||
maxMid = i
|
||||
radiusPos = i + point[i]
|
||||
}
|
||||
if maxLen < point[i]-1 && point[i]-1 > 1 {
|
||||
maxLen = point[i] - 1
|
||||
palindrome = allString[maxMid/2-maxLen/2 : radiusPos/2]
|
||||
}
|
||||
}
|
||||
|
||||
return maxLen, palindrome
|
||||
}
|
||||
|
||||
//把字符串转换成特殊的字符串
|
||||
func generateString(allString string) string {
|
||||
var result string
|
||||
for i := range allString {
|
||||
result = fmt.Sprintf("%s%s%c", result, "#", allString[i])
|
||||
}
|
||||
return fmt.Sprintf("%s%s", result, "#")
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/13 21:58
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package palindrome
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGenerateString(t *testing.T) {
|
||||
fmt.Println(generateString("abcdef"))
|
||||
fmt.Println(generateString("abc2342def"))
|
||||
fmt.Println(generateString("abcdef3213"))
|
||||
fmt.Println(generateString("abcderewrewr312f"))
|
||||
fmt.Println(generateString("312312abcdef321e"))
|
||||
}
|
||||
|
||||
func TestPalindrome(t *testing.T) {
|
||||
fmt.Println(Manacher("abcabccbacba"))
|
||||
fmt.Println(Manacher("mabcabccbacbammm"))
|
||||
fmt.Println(Manacher("habcabccbacbammm"))
|
||||
fmt.Println(Manacher("hmmmabcabccbacbammm"))
|
||||
fmt.Println(Manacher("abcdefghij"))
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/23 20:52
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
type AwardWeight struct {
|
||||
Award interface{} //奖励数据
|
||||
Weight int //权重
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/6/29 10:48
|
||||
* @Description:这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
@@ -47,7 +47,7 @@ func GetRandIntNoRepeat(count, min, max int) []int {
|
||||
return randAttr
|
||||
}
|
||||
|
||||
//从一个数组中获取到X个不重复随机数
|
||||
//从一个数组中获取到X个不重复下标的随机数
|
||||
func GetDiffNum(data []int, count int) []int {
|
||||
if count > len(data) {
|
||||
panic("获取随机数数量有误")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/6/29 10:23
|
||||
* @Description:这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/23 20:50
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
func GetAwardWeightByWeight(awardWeight []*AwardWeight) *AwardWeight {
|
||||
//求总权重
|
||||
weight := 0
|
||||
for _, award := range awardWeight {
|
||||
weight += award.Weight
|
||||
}
|
||||
randNum := GetRandInt(1, weight)
|
||||
sum := 0
|
||||
for _, award := range awardWeight {
|
||||
sum += award.Weight
|
||||
if sum >= randNum {
|
||||
return award
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//根据权重不放回的抽取,出参是:抽到的道具、剩余没有抽的道具
|
||||
func GetByWeightWithLeftAward(awardWeight []*AwardWeight) (*AwardWeight, []*AwardWeight) {
|
||||
weight := 0
|
||||
leftAwards := make([]*AwardWeight, 0)
|
||||
for _, award := range awardWeight {
|
||||
weight += award.Weight
|
||||
}
|
||||
randNum := GetRandInt(1, weight)
|
||||
sum := 0
|
||||
for index, award := range awardWeight {
|
||||
sum += award.Weight
|
||||
if sum >= randNum {
|
||||
//如果获取到奖励则将当前获取的奖励扣除
|
||||
leftAwards = append(awardWeight[0:index], awardWeight[index+1:]...)
|
||||
return award, leftAwards
|
||||
}
|
||||
}
|
||||
return nil, leftAwards
|
||||
}
|
||||
|
||||
// 根据权重不放回的抽取X个元素,直接返回这些元素
|
||||
// 入参:奖池、抽取数量,出参:获得的所有道具,剩余的其他道具
|
||||
func GetSomeAwardsFromPool(srcAwardPool []*AwardWeight, count int) ([]*AwardWeight, []*AwardWeight) {
|
||||
if count > len(srcAwardPool) {
|
||||
panic("抽取数量不对")
|
||||
}
|
||||
var finalAwardList []*AwardWeight
|
||||
var award *AwardWeight
|
||||
var leftAward = make([]*AwardWeight, len(srcAwardPool))
|
||||
copy(leftAward, srcAwardPool)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
award, leftAward = GetByWeightWithLeftAward(leftAward)
|
||||
finalAwardList = append(finalAwardList, award)
|
||||
}
|
||||
return finalAwardList, leftAward
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/23 22:08
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRandByAwardWeight(t *testing.T) {
|
||||
awardList := make([]*AwardWeight, 0)
|
||||
awardList = append(awardList, &AwardWeight{
|
||||
Award: []int{1, 2},
|
||||
Weight: 10,
|
||||
})
|
||||
awardList = append(awardList, &AwardWeight{
|
||||
Award: []int{2, 2},
|
||||
Weight: 20,
|
||||
})
|
||||
awardList = append(awardList, &AwardWeight{
|
||||
Award: []int{3, 2},
|
||||
Weight: 30,
|
||||
})
|
||||
|
||||
award := GetAwardWeightByWeight(awardList)
|
||||
fmt.Println(award.Award)
|
||||
|
||||
award1, list3 := GetByWeightWithLeftAward(awardList)
|
||||
fmt.Println(award1.Award)
|
||||
for _, award := range list3 {
|
||||
fmt.Println(award.Award)
|
||||
}
|
||||
|
||||
list4, left := GetSomeAwardsFromPool(awardList, 2)
|
||||
for _, award := range list4 {
|
||||
fmt.Println(award.Award)
|
||||
}
|
||||
for _, award := range left {
|
||||
fmt.Println(award.Award)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,7 @@ func LomutoPartition(list []int, start int, end int) int {
|
||||
if list[i] < compareValue {
|
||||
moveSubscript++
|
||||
charge++
|
||||
list[moveSubscript], list[i] = list[i], list[moveSubscript]
|
||||
list[moveSubscript], list[i] = list[i], list[moveSubscript] //交换元素
|
||||
}
|
||||
}
|
||||
charge++
|
||||
|
||||
@@ -13,17 +13,26 @@ import (
|
||||
|
||||
func TestPartition(t *testing.T) {
|
||||
list := []int{99, 1, 2, 3, 4, 100, 200, 90, 5}
|
||||
s := LomutoPartition(list, 0, 9-1)
|
||||
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s))
|
||||
for _, r := range list {
|
||||
fmt.Print(r, " ")
|
||||
|
||||
for i := 1; i <= len(list); i++ {
|
||||
s := LomutoPartition(list, 0, len(list)-1)
|
||||
fmt.Println()
|
||||
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s))
|
||||
for _, r := range list {
|
||||
fmt.Print(r, " ")
|
||||
}
|
||||
}
|
||||
|
||||
s = LomutoPartition(list, 0, 9-1)
|
||||
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s))
|
||||
for _, r := range list {
|
||||
fmt.Print(r, " ")
|
||||
fmt.Println()
|
||||
for i := 1; i <= len(list); i++ {
|
||||
num, _, _ := LomutoQuiteSelect(list, i)
|
||||
fmt.Println(fmt.Sprintf("第%d个位置的数是:%d", i, num))
|
||||
}
|
||||
|
||||
for i := 0; i < len(list); i++ {
|
||||
fmt.Println(list[i])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func doc() string {
|
||||
|
||||
@@ -17,6 +17,14 @@ func QuickSort(list []int, start, end int) {
|
||||
}
|
||||
}
|
||||
|
||||
func QuickSortByte(list []byte, start, end int) {
|
||||
if start < end {
|
||||
position := hoarePartition1(list, start, end)
|
||||
QuickSortByte(list, start, position) //注意这边结束的下表是position,而不是position + 1
|
||||
QuickSortByte(list, position+1, end)
|
||||
}
|
||||
}
|
||||
|
||||
//通过lomuto划分来实现快速排序
|
||||
func QuickSort1(list []int, start, end int) {
|
||||
if start < end {
|
||||
@@ -26,6 +34,25 @@ func QuickSort1(list []int, start, end int) {
|
||||
}
|
||||
}
|
||||
|
||||
func hoarePartition1(list []byte, start int, end int) int {
|
||||
value := list[start] //比较的元素
|
||||
s := start
|
||||
e := end
|
||||
for s < e {
|
||||
//找到数组终止前,比目标数(value)大的数字
|
||||
for ; s < end && list[s] < value; s++ {
|
||||
}
|
||||
//找到数组结束前,比目标数(value)小的数字
|
||||
for ; e > start && list[e] >= value; e-- {
|
||||
}
|
||||
if s < e {
|
||||
list[s], list[e] = list[e], list[s]
|
||||
}
|
||||
}
|
||||
list[start], list[e] = list[e], list[start]
|
||||
return e
|
||||
}
|
||||
|
||||
func hoarePartition(list []int, start int, end int) int {
|
||||
value := list[start] //比较的元素
|
||||
s := start
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
## 需求
|
||||
这里的实际需求是策划案中的掷骰子,先随机得到骰子的总和,再将骰子拆分成三个随机的骰子数,策划案中说明有对出现豹子进行控制,这边不把这个实现做进来
|
||||
如果需要进行控制,则在获取结果之后进行控制即可,重新掷骰子的概率不会特别高,因为豹子本身就是一个低概率的事件。
|
||||
|
||||
|
||||
## 实现
|
||||
总共两个实现,一个是实际需求中的三个数的拆分
|
||||
|
||||
另一个是N个数的拆分,这边用Splitter结构体实现,在创建的时候需要进行数字与数量的校验
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* @Author : huangZJ
|
||||
* @Time : 2021/6/16 10:50
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package splitNumToN
|
||||
|
||||
import (
|
||||
"Go-Tool/util/rand"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//将一个数拆解成三个
|
||||
func SplitNumTo3(num int) {
|
||||
randNumList := make([]int, 0)
|
||||
var count int
|
||||
for i := 0; i < 2; i++ {
|
||||
randNum := getRandValue(num-count, 3-1-i)
|
||||
randNumList = append(randNumList, randNum)
|
||||
count = count + randNum
|
||||
}
|
||||
|
||||
randNumList = append(randNumList, num-count)
|
||||
|
||||
for _, num := range randNumList {
|
||||
fmt.Print(fmt.Sprintf("%d ", num))
|
||||
}
|
||||
}
|
||||
|
||||
//num 被随机的数
|
||||
//count count + 1 = 总随机数数量
|
||||
func getRandValue(num int, count int) int {
|
||||
minValue := num - 6*count
|
||||
if minValue <= 0 {
|
||||
minValue = 1
|
||||
}
|
||||
maxValue := num - count*1
|
||||
if maxValue > 6 {
|
||||
maxValue = 6
|
||||
}
|
||||
|
||||
return rand.GetRandInt(minValue, maxValue)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* @Author : huangZJ
|
||||
* @Time : 2021/6/16 10:52
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package splitNumToN
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplitNumTo3(t *testing.T) {
|
||||
for i := 4; i <= 17; i++ {
|
||||
fmt.Println()
|
||||
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
|
||||
for j := 0; j < 100; j++ {
|
||||
fmt.Println()
|
||||
SplitNumTo3(i)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* @Author : huangZJ
|
||||
* @Time : 2021/6/15 11:20
|
||||
* @Description:将一个数拆分成其他N个数,这N个数相加的结果等于这个数
|
||||
*/
|
||||
|
||||
package splitNumToN
|
||||
|
||||
import "Go-Tool/util/rand"
|
||||
|
||||
type Splitter struct {
|
||||
NumCount int //拆分成随机数的数量
|
||||
Num int //被拆分的总数
|
||||
MinValue int //被拆分的最小值
|
||||
MaxValue int //被拆分的最大值
|
||||
|
||||
SplitNumList []int //存放拆解之后的结果
|
||||
}
|
||||
|
||||
func NewSplitter(numCount, num int) *Splitter {
|
||||
//给定默认的限制的最大最小值
|
||||
splitter := &Splitter{
|
||||
NumCount: numCount,
|
||||
Num: num,
|
||||
MinValue: 1,
|
||||
MaxValue: 6,
|
||||
SplitNumList: make([]int, 0),
|
||||
}
|
||||
//校验数值是否满足
|
||||
splitter.checkValue()
|
||||
return splitter
|
||||
}
|
||||
|
||||
func (splitter *Splitter) checkValue() {
|
||||
if splitter.MinValue*splitter.NumCount > splitter.Num {
|
||||
panic("被拆分的数值过小")
|
||||
}
|
||||
if splitter.MaxValue*splitter.NumCount < splitter.Num {
|
||||
panic("被拆分的数值过大")
|
||||
}
|
||||
}
|
||||
|
||||
//将一个数拆成N个,并且保证N个数相加值等于被拆分的这个数
|
||||
func (splitter *Splitter) SplitNumToN() {
|
||||
var count int
|
||||
for i := 0; i < splitter.NumCount-1; i++ {
|
||||
randNum := splitter.getRandValue(splitter.Num-count, splitter.NumCount-1-i)
|
||||
splitter.SplitNumList = append(splitter.SplitNumList, randNum)
|
||||
count = count + randNum
|
||||
}
|
||||
|
||||
splitter.SplitNumList = append(splitter.SplitNumList, splitter.Num-count)
|
||||
}
|
||||
|
||||
func (splitter *Splitter) GetRandNumList() []int {
|
||||
return splitter.SplitNumList
|
||||
}
|
||||
|
||||
//num 被随机的数
|
||||
//count count + 1 = 总随机数数量
|
||||
func (splitter *Splitter) getRandValue(num int, count int) int {
|
||||
minValue := num - splitter.MaxValue*count
|
||||
if minValue <= 0 {
|
||||
minValue = splitter.MinValue
|
||||
}
|
||||
maxValue := num - count*1
|
||||
if maxValue > splitter.MaxValue {
|
||||
maxValue = splitter.MaxValue
|
||||
}
|
||||
|
||||
return rand.GetRandInt(minValue, maxValue)
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* @Author : huangZJ
|
||||
* @Time : 2021/6/16 9:50
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package splitNumToN
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplitNumToNWith2(t *testing.T) {
|
||||
|
||||
fmt.Println("测试两个数的情况")
|
||||
for i := 3; i <= 11; i++ {
|
||||
fmt.Println()
|
||||
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
|
||||
for j := 0; j < 20; j++ {
|
||||
splitter := NewSplitter(2, i)
|
||||
splitter.SplitNumToN()
|
||||
for _, num := range splitter.GetRandNumList() {
|
||||
fmt.Print(fmt.Sprintf("%d ", num))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitNumToNWith3(t *testing.T) {
|
||||
fmt.Println()
|
||||
fmt.Println("测试三个数的情况")
|
||||
for i := 4; i <= 17; i++ {
|
||||
fmt.Println()
|
||||
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
|
||||
for j := 0; j < 20; j++ {
|
||||
splitter := NewSplitter(3, i)
|
||||
fmt.Println()
|
||||
splitter.SplitNumToN()
|
||||
for _, num := range splitter.GetRandNumList() {
|
||||
fmt.Print(fmt.Sprintf("%d ", num))
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitNumToNWith4(t *testing.T) {
|
||||
fmt.Println()
|
||||
fmt.Println("测试四个数的情况")
|
||||
for i := 5; i <= 23; i++ {
|
||||
fmt.Println()
|
||||
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
|
||||
for j := 0; j < 100; j++ {
|
||||
splitter := NewSplitter(4, i)
|
||||
fmt.Println()
|
||||
splitter.SplitNumToN()
|
||||
for _, num := range splitter.GetRandNumList() {
|
||||
fmt.Print(fmt.Sprintf("%d ", num))
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitNumToNWith5(t *testing.T) {
|
||||
fmt.Println()
|
||||
fmt.Println("测试五个数的情况")
|
||||
for i := 6; i <= 29; i++ {
|
||||
fmt.Println()
|
||||
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
|
||||
for j := 0; j < 100; j++ {
|
||||
splitter := NewSplitter(5, i)
|
||||
fmt.Println()
|
||||
splitter.SplitNumToN()
|
||||
for _, num := range splitter.GetRandNumList() {
|
||||
fmt.Print(fmt.Sprintf("%d ", num))
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSplitNumToNWith6(t *testing.T) {
|
||||
fmt.Println()
|
||||
fmt.Println("测试六个数的情况")
|
||||
for i := 7; i <= 35; i++ {
|
||||
fmt.Println()
|
||||
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
|
||||
for j := 0; j < 100; j++ {
|
||||
splitter := NewSplitter(6, i)
|
||||
fmt.Println()
|
||||
splitter.SplitNumToN()
|
||||
for _, num := range splitter.GetRandNumList() {
|
||||
fmt.Print(fmt.Sprintf("%d ", num))
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,15 @@ import (
|
||||
func TestHorspool(t *testing.T) {
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "abcd")) //输出0
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "bcd")) //输出1
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "fgh")) //输出6
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "hijk")) //输出8
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "jk")) //输出10
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "k")) //输出11
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "fgh")) //输出5
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "hijk")) //输出7
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "jk")) //输出9
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "k")) //输出10
|
||||
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "kbz")) //输出-1
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "kdasdsad")) //输出-1
|
||||
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "dsadsa")) //输出-1
|
||||
|
||||
fmt.Println(shiTable("abdabe"))
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/24 13:19
|
||||
* @Description:KMP字符串匹配算法,参考地址:https://www.cnblogs.com/en-heng/p/5091365.html
|
||||
* http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
func KmpMatch(allString string, match string) int {
|
||||
next := getNext(match)
|
||||
i := 0 //被匹配的字符串下标
|
||||
j := 0 //模式匹配字符串下标
|
||||
sLength := len(allString) - 1
|
||||
mLength := len(match) - 1
|
||||
for i <= sLength && j <= mLength {
|
||||
if j == -1 || allString[i] == match[j] {
|
||||
j++
|
||||
i++
|
||||
} else {
|
||||
j = next[j]
|
||||
}
|
||||
}
|
||||
|
||||
if j == len(match) {
|
||||
return i - j
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
//失配表函数构建(部分匹配函数)
|
||||
func getNext(match string) []int {
|
||||
next := make([]int, len(match))
|
||||
next[0] = -1
|
||||
i := 0
|
||||
j := -1
|
||||
|
||||
mLength := len(match) - 1
|
||||
|
||||
for i < mLength {
|
||||
//处理两种情况: 1.数组第一个数是-1 2. match对应位置字符相等的情况
|
||||
if j == -1 || match[i] == match[j] {
|
||||
//如果这里是数组第一个数的时候,下标要往后移动
|
||||
//如果这里是数组相等的情况,要比较下一个相应的字符,所以下标需要往后移动,而next需要在上一个的基础上去做+1操作
|
||||
i++
|
||||
j++
|
||||
next[i] = j
|
||||
} else {
|
||||
//如果匹配过程中,出现对应不上的情况,也就是说 match[i] != match[j],
|
||||
j = next[j]
|
||||
}
|
||||
}
|
||||
|
||||
return next
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/24 17:52
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKmpMatch(t *testing.T) {
|
||||
s := "abcbvxs"
|
||||
m := "bcb"
|
||||
showResult(s, m)
|
||||
s = "abcbvxs"
|
||||
m = "bx"
|
||||
showResult(s, m)
|
||||
s = "abcbvxssdaadsad"
|
||||
m = "cbvxssdaa"
|
||||
showResult(s, m)
|
||||
}
|
||||
|
||||
func TestMatchNum(t *testing.T) {
|
||||
s := "ababababca"
|
||||
m := "abababca"
|
||||
showResult(s, m)
|
||||
}
|
||||
|
||||
func showResult(s, m string) {
|
||||
i := KmpMatch(s, m)
|
||||
if i == -1 {
|
||||
fmt.Println("未找到对应字符串")
|
||||
} else {
|
||||
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNext(t *testing.T) {
|
||||
next := getNext("abababca")
|
||||
fmt.Println(next)
|
||||
next1 := getNext("abababc")
|
||||
fmt.Println(next1)
|
||||
next2 := getNext("abababcxy")
|
||||
fmt.Println(next2)
|
||||
next3 := getNext("abababcxyxyy")
|
||||
fmt.Println(next3)
|
||||
next4 := getNext("abcdabd")
|
||||
fmt.Println(next4)
|
||||
next5 := getNext("abcxabcxabcyabcz")
|
||||
fmt.Println(next5)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/5 13:17
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
func KarpRabinMatch(allString, modeString string) int {
|
||||
hashMode := hash(modeString)
|
||||
for i := 0; i < len(allString)-len(modeString)+1; i++ {
|
||||
hashKey := hash(allString[i : i+len(modeString)+1])
|
||||
if hashMode == hashKey {
|
||||
for j := 0; j < len(modeString); j++ {
|
||||
if allString[i+j] != modeString[j] {
|
||||
break
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func hash(s string) int {
|
||||
return 1
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/5 13:25
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKarpRabinMatch(t *testing.T) {
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "abcd")) //输出0
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "bcd")) //输出1
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "fgh")) //输出5
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "hijk")) //输出7
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "jk")) //输出9
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "k")) //输出10
|
||||
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "kbz")) //输出-1
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "kdasdsad")) //输出-1
|
||||
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "dsadsa")) //输出-1
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/8 14:42
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
import "fmt"
|
||||
|
||||
func ShiftAndMatch(allString, modeString string) int {
|
||||
if len(modeString) > 32 {
|
||||
panic("暂只支持32位大小")
|
||||
}
|
||||
|
||||
bitap := GenerateTable(modeString)
|
||||
|
||||
fmt.Println("bitap的二进制:")
|
||||
for i := 0; i < len(modeString); i++ {
|
||||
fmt.Println(fmt.Sprintf("当前字符:%c,对应二进制:%08b", modeString[i], bitap[modeString[i]-'a']))
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
|
||||
var status int
|
||||
for i := 0; i < len(allString); i++ {
|
||||
status = ((status << 1) | 1) & bitap[allString[i]-'a']
|
||||
fmt.Println(fmt.Sprintf("当前字符:%c,对应的二进制结果:%08b", allString[i], status))
|
||||
if status&(1<<(len(modeString)-1)) > 0 {
|
||||
return i - len(modeString) + 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func GenerateTable(modeString string) []int {
|
||||
bitap := make([]int, 32)
|
||||
for i := 0; i < len(modeString); i++ {
|
||||
bitap[modeString[i]-'a'] |= 1 << i
|
||||
}
|
||||
return bitap
|
||||
}
|
||||
|
||||
func ShiftOrMatch(allString, modeString string) int {
|
||||
if len(modeString) > 32 {
|
||||
panic("暂只支持32位大小")
|
||||
}
|
||||
|
||||
bitap := make([]int, 32)
|
||||
for i := 0; i < 32; i++ {
|
||||
bitap[i] = ^0
|
||||
}
|
||||
|
||||
var shift = 1
|
||||
for i := 0; i < len(modeString); i++ {
|
||||
bitap[modeString[i]-'a'] &= ^shift
|
||||
shift <<= 1
|
||||
}
|
||||
|
||||
fmt.Println("bitap的二进制:")
|
||||
for i := 0; i < len(modeString); i++ {
|
||||
fmt.Println(fmt.Sprintf("当前字符:%c,对应二进制:%08b", modeString[i], uint32(bitap[modeString[i]-'a'])))
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
status := ^0
|
||||
mask := ^(1 << (len(modeString) - 1))
|
||||
fmt.Println(fmt.Sprintf("mask:%08b", uint32(mask)))
|
||||
for i := 0; i < len(allString); i++ {
|
||||
status = (status << 1) | bitap[allString[i]-'a']
|
||||
fmt.Println(fmt.Sprintf("当前字符:%c,对应的二进制结果:%08b", allString[i], uint32(status)))
|
||||
if ^(status | mask) > 0 {
|
||||
return i - len(modeString) + 1
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/8 14:51
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestShiftAndMatch(t *testing.T) {
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "abcd")) //输出0
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "bcd")) //输出1
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "fgh")) //输出5
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "hijk")) //输出7
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "jk")) //输出9
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "k")) //输出10
|
||||
//
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "kbz")) //输出-1
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "kdasdsad")) //输出-1
|
||||
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "dsadsa")) //输出-1
|
||||
|
||||
fmt.Println("该子串的位置为:", ShiftAndMatch("cbcbcbaefd", "cbcba"))
|
||||
}
|
||||
|
||||
func TestShiftOrMatch(t *testing.T) {
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "abcd")) //输出0
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "bcd")) //输出1
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "fgh")) //输出5
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "hijk")) //输出7
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "jk")) //输出9
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "k")) //输出10
|
||||
//
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "kbz")) //输出-1
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "kdasdsad")) //输出-1
|
||||
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "dsadsa")) //输出-1
|
||||
|
||||
fmt.Println("该子串的位置为:", ShiftOrMatch("cbcbcbaefd", "cbcba"))
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/2 11:21
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
func ShiftTable(mode string) []int {
|
||||
shiftTable := make([]int, 256)
|
||||
|
||||
//一开始设置所有的字符匹配不上向右移动大小为:模式字符串长度 + 1(因为要移动到下一个字符的后一位)
|
||||
for i := range shiftTable {
|
||||
shiftTable[i] = len(mode) + 1
|
||||
}
|
||||
|
||||
//设置模式字符串中每一个字符的移动长度.
|
||||
for i := range mode {
|
||||
shiftTable[mode[i]] = len(mode) - i
|
||||
}
|
||||
|
||||
return shiftTable
|
||||
}
|
||||
|
||||
func SundayMatch(allString, modeString string) int {
|
||||
table := ShiftTable(modeString)
|
||||
aLength := len(allString)
|
||||
mLength := len(modeString)
|
||||
i := 0 //这个参数记录的是移动过程中,,模式字符串对应原始字符串的第一个位置.
|
||||
|
||||
for i < aLength-mLength {
|
||||
j := 0
|
||||
for allString[i+j] == modeString[j] {
|
||||
j++
|
||||
if j >= len(modeString) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
//找到移动后模式字符串对应原始字符串的第一个位置
|
||||
move := allString[i+mLength]
|
||||
i = i + table[move]
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/3/2 11:21
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSundayMatch(t *testing.T) {
|
||||
s := "abcbvxs"
|
||||
m := "bcb"
|
||||
showResult2(s, m)
|
||||
s = "abcbvxs"
|
||||
m = "bx"
|
||||
showResult2(s, m)
|
||||
s = "abcbvxssdaadsad"
|
||||
m = "cbvxssdaa"
|
||||
showResult2(s, m)
|
||||
}
|
||||
|
||||
func showResult2(s, m string) {
|
||||
i := SundayMatch(s, m)
|
||||
if i == -1 {
|
||||
fmt.Println("未找到对应字符串")
|
||||
} else {
|
||||
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/25 11:11
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
func ViolentMatch(allString, match string) int {
|
||||
i := 0
|
||||
j := 0
|
||||
sLength := len(allString)
|
||||
mLenght := len(match)
|
||||
|
||||
for i < sLength && j < mLenght {
|
||||
//当前字符如果匹配,继续匹配下一个字符,坐标移动
|
||||
if allString[i] == match[j] {
|
||||
j++
|
||||
i++
|
||||
} else {
|
||||
//如果字符不匹配,match从头开始,被匹配的字符串从之前匹配的下一个字符开始,坐标修改
|
||||
i = i - j + 1
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
|
||||
if j == len(match) {
|
||||
return i - j
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/25 11:11
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package stringMatch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestViolentMatch(t *testing.T) {
|
||||
s := "abcbvxs"
|
||||
m := "bcb"
|
||||
showResult1(s, m)
|
||||
s = "abcbvxs"
|
||||
m = "bx"
|
||||
showResult1(s, m)
|
||||
s = "abcbvxssdaadsad"
|
||||
m = "cbvxssdaa"
|
||||
showResult1(s, m)
|
||||
}
|
||||
|
||||
func showResult1(s, m string) {
|
||||
i := ViolentMatch(s, m)
|
||||
if i == -1 {
|
||||
fmt.Println("未找到对应字符串")
|
||||
} else {
|
||||
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,15 @@ func TestTimeIntervalUtil(t *testing.T) {
|
||||
o2 := GetIntervalBetweenTimes(time.Now().AddDate(3, 2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix(), time.Now().Unix())
|
||||
o3 := GetIntervalBetweenTimes(time.Now().Unix(), time.Now().AddDate(3, -2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix())
|
||||
|
||||
O4 := GetIntervalDay(time.Now(), time.Now().AddDate(0, 0, 2))
|
||||
O5 := GetIntervalDay(time.Now(), time.Now().AddDate(0, 0, 2).Add(5*time.Hour))
|
||||
O6 := GetIntervalDay(time.Now(), time.Now().AddDate(0, 0, 2).Add(25*time.Hour))
|
||||
|
||||
fmt.Println("相差天数计算:")
|
||||
fmt.Println(O4)
|
||||
fmt.Println(O5)
|
||||
fmt.Println(O6)
|
||||
|
||||
ox := GetIntervalBetweenTimes(time.Now().Unix(), time.Date(2020, 5, 6, 0, 0, 0, 0, time.Local).Unix())
|
||||
fmt.Println(ox)
|
||||
|
||||
|
||||
@@ -136,6 +136,20 @@ func GetIntervalBetweenTimes(timestamp, stamp int64) vo.IntervalObj {
|
||||
|
||||
}
|
||||
|
||||
// 获取两个时间点之间相差多少天
|
||||
func GetIntervalDay(beforeTime, afterTime time.Time) int {
|
||||
timestamp := beforeTime.Unix()
|
||||
stamp := afterTime.Unix()
|
||||
//时间大小保证前小后大
|
||||
if timestamp > stamp {
|
||||
timestamp, stamp = stamp, timestamp
|
||||
}
|
||||
timeBefore := time.Unix(timestamp, 0)
|
||||
timeAfter := time.Unix(stamp, 0)
|
||||
m := timeAfter.Sub(timeBefore)
|
||||
return int(m.Hours() / 24)
|
||||
}
|
||||
|
||||
/*
|
||||
* @param timestamp 时间戳
|
||||
* @param stamp 时间戳
|
||||
|
||||
+10
-2
@@ -32,7 +32,7 @@ func initTrie() *Trie {
|
||||
}
|
||||
|
||||
//往前缀树中添加对应的字符串(build模式)
|
||||
func (trie *Trie) insert(word string) *Trie {
|
||||
func (trie *Trie) Insert(word string) *Trie {
|
||||
traverse := trie
|
||||
for _, v := range []rune(word) {
|
||||
if _, ok := traverse.Child[v]; !ok {
|
||||
@@ -48,13 +48,21 @@ func (trie *Trie) insert(word string) *Trie {
|
||||
//删除对应的字符串,如果查找不到则直接返回(build模式)
|
||||
func (trie *Trie) Delete(word string) *Trie {
|
||||
traverse := trie
|
||||
parent := trie
|
||||
var value rune
|
||||
for _, v := range []rune(word) {
|
||||
if _, ok := traverse.Child[v]; !ok {
|
||||
return trie
|
||||
}
|
||||
parent = traverse
|
||||
traverse = traverse.Child[v]
|
||||
value = v
|
||||
}
|
||||
traverse.Word = emptyTag
|
||||
if len(parent.Child) == 0 {
|
||||
delete(parent.Child, value)
|
||||
return trie
|
||||
}
|
||||
parent.Child[value].Word = emptyTag
|
||||
return trie
|
||||
}
|
||||
|
||||
|
||||
+12
-10
@@ -14,15 +14,16 @@ import (
|
||||
//模糊查询前缀匹配的所有字符串
|
||||
func TestSearchTrieVague(t *testing.T) {
|
||||
fmt.Println()
|
||||
fmt.Println("模糊查询 查找前缀匹配的所有字符串")
|
||||
fmt.Println("模糊查询 查找前缀匹配的所有字符串,输入\"新年快乐\" ")
|
||||
trie := New()
|
||||
trie.insert("abcuuid").insert("abcuued").insert("abcMxns").insert("abssde").insert("avddfa")
|
||||
trie.insert("我爱中国").insert("我爱祖国").insert("我爱学习").insert("我是谁").insert("我在哪里")
|
||||
trie.insert("我是你").insert("我").insert("我喜欢学习").insert("我在厦门").insert("我是一个程序员")
|
||||
trie.Insert("abcuuid").Insert("abcuued").Insert("abcMxns").Insert("abssde").Insert("avddfa")
|
||||
trie.Insert("我爱中国").Insert("我爱祖国").Insert("我爱学习").Insert("我是谁").Insert("我在哪里")
|
||||
trie.Insert("我是你").Insert("我").Insert("我喜欢学习").Insert("我在厦门").Insert("我是一个程序员")
|
||||
trie.Insert("新年快乐,你好呀").Insert("新年新气象").Insert("新的一年新的开始")
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
result3, _ := trie.SearchTrieVague("我爱她")
|
||||
result3, _ := trie.SearchTrieVague("新年快乐")
|
||||
for _, r := range result3 {
|
||||
fmt.Println(r)
|
||||
}
|
||||
@@ -33,8 +34,8 @@ func TestSearchTrie(t *testing.T) {
|
||||
fmt.Println()
|
||||
fmt.Println("查找前缀匹配的所有字符串")
|
||||
trie := New()
|
||||
trie.insert("abcuuid").insert("abcuued").insert("abcMxns").insert("abssde").insert("avddfa")
|
||||
trie.insert("我爱中国").insert("我爱祖国").insert("我爱学习").insert("我是谁").insert("我在哪里")
|
||||
trie.Insert("abcuuid").Insert("abcuued").Insert("abcMxns").Insert("abssde").Insert("avddfa")
|
||||
trie.Insert("我爱中国").Insert("我爱祖国").Insert("我爱学习").Insert("我是谁").Insert("我在哪里")
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
@@ -62,7 +63,7 @@ func TestSearchTrie(t *testing.T) {
|
||||
//敏感词汇屏蔽测试
|
||||
func TestSensitiveWordsTest(t *testing.T) {
|
||||
trie := New()
|
||||
trie.insert("粗话").insert("fuck").insert("fuckk").insert("脏话")
|
||||
trie.Insert("粗话").Insert("fuck").Insert("fuckk").Insert("脏话")
|
||||
s := "我是脏话,我是粗话,fuckk,fuck,fffuccck"
|
||||
word := trie.DealFunc(s, func(sentence []rune, start int, end int) string {
|
||||
var replace string
|
||||
@@ -73,13 +74,14 @@ func TestSensitiveWordsTest(t *testing.T) {
|
||||
runes = append(runes, sentence[end:]...)
|
||||
return string(runes)
|
||||
})
|
||||
fmt.Println(word)
|
||||
fmt.Println(fmt.Sprintf("原来的字符串: \"%v\"", s))
|
||||
fmt.Println(fmt.Sprintf("转换后的字符串: \"%v\"", word))
|
||||
}
|
||||
|
||||
//常规功能测试
|
||||
func TestCommonTest(t *testing.T) {
|
||||
trie := New()
|
||||
trie.insert("ABC").insert("AB").insert("ABE").insert("ABEX").insert("XYZ").insert("你").insert("你好").insert("你是谁")
|
||||
trie.Insert("ABC").Insert("AB").Insert("ABE").Insert("ABEX").Insert("XYZ").Insert("你").Insert("你好").Insert("你是谁")
|
||||
result := trie.Traverse()
|
||||
for _, r := range result {
|
||||
fmt.Println(r)
|
||||
|
||||
Reference in New Issue
Block a user