剑指offer 丑数 (三指针法)

剑指 Offer 49. 丑数
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

示例:

输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
说明:

1 是丑数。
n 不超过1690。

解析:
方法1:优先队列思想,map去重
从丑数1开始算起,分别乘以2,3,5,然后将结果放入优先队列中,采用map去重,每次取最小的丑数分别再乘以2,3,5,一直计算下去,直到得到第n个丑数为止

var dp [1700]int
func nthUglyNumber(n int) int {
	dp[1]=1
	if dp[n]!=0{
		return dp[n]
	}

	count:=1
	index:=1
	aMap:=make(map[int]int)

	for count<n{
		aMap[index*2]=1
		aMap[index*3]=1
		aMap[index*5]=1

		minKey:=index*2
		for key:= range aMap{
			if key<minKey{
				minKey=key
			}
		}

		index=minKey
		count++
		delete(aMap,index)

	}

	dp[n]=index
	return index
}

方法2:三指针法
核心思想:每个丑数都是其他丑数或乘以2,或乘以3,或乘以5得到的,同理,每个丑数都需要乘以2,乘以3,乘以5,来得到其他的丑数,那可以有三个指针,p2,p3,p5
p2:指向还未乘以2的丑数的位置
p3:指向还未乘以3的丑数的位置
p5:指向还未乘以5的丑数的位置
那么可以得到状态转移方程
dp[i]=min(dp[p2],dp[p3],dp[p5])
看看当前dp[i]是由那个指针得到的,将那个指针向前移动一位即可
注意重复的情况,有的时候,同一个丑数可以由两个不同的指针得到,比如6,可以是32,也可以是23,这个时候,p2,p3指针都应该移动
时间复杂度:O(N)
空间复杂度:O(N)

var dp [1700]int
func Min(a,b,c int) int{
	minValue:=a
	if minValue>b{
		minValue=b
	}
	if minValue>c{
		minValue=c
	}
	return minValue
}
func nthUglyNumber(n int) int {
	if dp[n]!=0{
		return dp[n]
	}

	dp[1]=1
	p2,p3,p5:=1,1,1
	for i:=2;i<=n;i++{
		a:=dp[p2]*2
		b:=dp[p3]*3
		c:=dp[p5]*5
		dp[i]=Min(a,b,c)
		if dp[i]==a{
			p2++
		}
		if dp[i]==b{
			p3++
		}
		if dp[i]==c {
			p5++
		}
	}

	return dp[n]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章