diff --git a/algorithm/numberList/IAlgorithm.go b/algorithm/numberList/IAlgorithm.go new file mode 100644 index 0000000..08b34a0 --- /dev/null +++ b/algorithm/numberList/IAlgorithm.go @@ -0,0 +1,11 @@ +/* + * @Author : huangzj + * @Time : 2021/3/16 16:46 + * @Description: + */ + +package numberList + +type i interface { + Doc() string +} diff --git a/algorithm/numberList/NumberCount/OnlyOneNumberOtherK.go b/algorithm/numberList/NumberCount/OnlyOneNumberOtherK.go new file mode 100644 index 0000000..cbbfa97 --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyOneNumberOtherK.go @@ -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 +} diff --git a/algorithm/numberList/NumberCount/OnlyOneNumberOtherK_test.go b/algorithm/numberList/NumberCount/OnlyOneNumberOtherK_test.go new file mode 100644 index 0000000..4f2f245 --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyOneNumberOtherK_test.go @@ -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 + +} diff --git a/algorithm/numberList/NumberCount/OnlyOneNumberOtherThree.go b/algorithm/numberList/NumberCount/OnlyOneNumberOtherThree.go new file mode 100644 index 0000000..d7ba375 --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyOneNumberOtherThree.go @@ -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) +} diff --git a/algorithm/numberList/NumberCount/OnlyOneNumberOtherThree_test.go b/algorithm/numberList/NumberCount/OnlyOneNumberOtherThree_test.go new file mode 100644 index 0000000..46794c0 --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyOneNumberOtherThree_test.go @@ -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 +} diff --git a/algorithm/numberList/NumberCount/OnlyOneNumberShowOnce.go b/algorithm/numberList/NumberCount/OnlyOneNumberShowOnce.go new file mode 100644 index 0000000..7c05f35 --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyOneNumberShowOnce.go @@ -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 +} diff --git a/algorithm/numberList/NumberCount/OnlyOneNumberShowOnce_test.go b/algorithm/numberList/NumberCount/OnlyOneNumberShowOnce_test.go new file mode 100644 index 0000000..0c30a4a --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyOneNumberShowOnce_test.go @@ -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 +} diff --git a/algorithm/numberList/NumberCount/OnlyTwoNumberShowOnce.go b/algorithm/numberList/NumberCount/OnlyTwoNumberShowOnce.go new file mode 100644 index 0000000..8b98dc6 --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyTwoNumberShowOnce.go @@ -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 +} diff --git a/algorithm/numberList/NumberCount/OnlyTwoNumberShowOnce_test.go b/algorithm/numberList/NumberCount/OnlyTwoNumberShowOnce_test.go new file mode 100644 index 0000000..d64e688 --- /dev/null +++ b/algorithm/numberList/NumberCount/OnlyTwoNumberShowOnce_test.go @@ -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 +} diff --git a/algorithm/numberList/NumberMoreThan/NumberMoreThanHalf.go b/algorithm/numberList/NumberMoreThan/NumberMoreThanHalf.go new file mode 100644 index 0000000..ab2b70d --- /dev/null +++ b/algorithm/numberList/NumberMoreThan/NumberMoreThanHalf.go @@ -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 +} diff --git a/algorithm/numberList/NumberMoreThan/NumberMoreThanHalf_test.go b/algorithm/numberList/NumberMoreThan/NumberMoreThanHalf_test.go new file mode 100644 index 0000000..c034018 --- /dev/null +++ b/algorithm/numberList/NumberMoreThan/NumberMoreThanHalf_test.go @@ -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 +} diff --git a/algorithm/numberList/NumberMoreThan/NumberMoreThanK.go b/algorithm/numberList/NumberMoreThan/NumberMoreThanK.go new file mode 100644 index 0000000..5eb8049 --- /dev/null +++ b/algorithm/numberList/NumberMoreThan/NumberMoreThanK.go @@ -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 +} diff --git a/algorithm/numberList/NumberMoreThan/NumberMoreThanK_test.go b/algorithm/numberList/NumberMoreThan/NumberMoreThanK_test.go new file mode 100644 index 0000000..1105a4b --- /dev/null +++ b/algorithm/numberList/NumberMoreThan/NumberMoreThanK_test.go @@ -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)) // +} diff --git a/readme.md b/readme.md index 206a8be..8d97a62 100644 --- a/readme.md +++ b/readme.md @@ -79,6 +79,8 @@ 2021/03/14: 新增Manacher算法,求最长回文串 +2021/03/18:新增超过半数数字系列算法题,新增出现次数不同的数字系列算法题 + # 修复日志 2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组)