feat(Go-Tool):2021/03/18:新增超过半数数字系列算法题,新增出现次数不同的数字系列算法题

This commit is contained in:
Huangzj
2021-03-18 15:55:40 +08:00
parent 8dbfebe5be
commit 00ada130fa
14 changed files with 441 additions and 0 deletions
@@ -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
}