劍指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]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章