970. 强整数

970. 强整数

970. 强整数

难度中等

给定两个正整数 xy,如果某一整数等于 x^i + y^j,其中整数 i >= 0j >= 0,那么我们认为该整数是一个强整数

返回值小于或等于 bound 的所有强整数组成的列表。

你可以按任何顺序返回答案。在你的回答中,每个值最多出现一次。

示例 1:

输入:x = 2, y = 3, bound = 10
输出:[2,3,4,5,7,9,10]
解释: 
2 = 2^0 + 3^0
3 = 2^1 + 3^0
4 = 2^0 + 3^1
5 = 2^1 + 3^1
7 = 2^2 + 3^1
9 = 2^3 + 3^0
10 = 2^0 + 3^2

示例 2:

输入:x = 3, y = 5, bound = 15
输出:[2,4,6,8,10,14]

提示:

  • 1 <= x <= 100
  • 1 <= y <= 100
  • 0 <= bound <= 10^6

函数签名:

func powerfulIntegers(x, y, bound int) []int

分析

这个问题很独特,独特在没有比朴素解法更好的解法~

朴素解法很容易想到,先分析下复杂度怎么样。

假设 xy 都比 1 大,要满足 xi+yjboundx^i+y^j \le bound ,显然 ij 有上限,分别是 logxboundlog_{x}boundlogyboundlog_{y}bound

根据题目约束,这两个值不会大于 20,这样就可以用朴素解法。

func powerfulIntegers(x, y, bound int) []int {
	px, py := 0, 0 // x 和 y 的指数上限。如果 x 是 1,px 就是 0,y 和 py 同理
	if x > 1 {
		px = int(math.Log2(float64(bound)) / math.Log2(float64(x))) // log(x, bound)
	}
	if y > 1 {
		py = int(math.Log2(float64(bound)) / math.Log2(float64(y))) // log(y, bound)
	}
	set := map[int]bool{} // 用集合去重
	powX := 1             // x^i
	for i := 0; i <= px; i++ {
		powY := 1 // y^j
		for j := 0; j <= py; j++ {
			val := powX + powY
			if val > bound {
				break
			}
			set[val] = true
			powY *= y
		}
		powX *= x
	}
	res := make([]int, 0, len(set))
	for k := range set {
		res = append(res, k)
	}
	return res
}

时间复杂度是 O(XY)XY 就是两个指数上限值,各自不会超过 20 。