題目描述:咱們把只包含因子 二、3 和 5 的數稱做醜數(Ugly Number)。求按從小到大的順序的第 n 個醜數。javascript
由於醜數只包含質因數 2, 3, 5,因此對於下個醜數來講,必定是前面某個醜數乘 三、乘 4 或者乘 5 所得。java
準備三個指針 ptr二、ptr三、ptr5,它們指向的數只能乘 二、3 和 5。在循環過程當中,每次選取 2 * res[ptr2]
、3 * res[ptr3]
和 5 * res[ptr5]
這三個數中結果最小的數,而且將對應的指針向前移動。有效循環是 n 次,當循環結束後,res 數組中就按從小到大的順序保存了醜數。git
代碼以下:github
// ac地址:https://leetcode-cn.com/problems/ugly-number-ii/ // 原文地址:https://xxoo521.com/2020-03-10-ugly-number-ii/ /** * @param {number} n * @return {number} */ var nthUglyNumber = function(n) { const res = new Array(n); res[0] = 1; let ptr2 = 0, // 下個數字永遠 * 2 ptr3 = 0, // 下個數字永遠 * 3 ptr5 = 0; // 下個數字永遠 * 5 for (let i = 1; i < n; ++i) { res[i] = Math.min(res[ptr2] * 2, res[ptr3] * 3, res[ptr5] * 5); // 說明前ptr2個醜數*2也不可能產生比i更大的醜數了 // 因此移動ptr2 if (res[i] === res[ptr2] * 2) { ++ptr2; } if (res[i] === res[ptr3] * 3) { ++ptr3; } if (res[i] === res[ptr5] * 5) { ++ptr5; } } return res[n - 1]; };
時間複雜度是\(O(N)\),空間複雜度是\(O(N)\)。算法
藉助最小堆,能夠在 \(O(LogN)\) 時間複雜度內找到當前最小的元素。總體算法流程是:數組
代碼實現以下:this
// ac地址:https://leetcode-cn.com/problems/ugly-number-ii/ // 原文地址:https://xxoo521.com/2020-03-10-ugly-number-ii/ const defaultCmp = (x, y) => x > y; const swap = (arr, i, j) => ([arr[i], arr[j]] = [arr[j], arr[i]]); class Heap { /** * 默認是最大堆 * @param {Function} cmp */ constructor(cmp = defaultCmp) { this.container = []; this.cmp = cmp; } insert(data) { const { container, cmp } = this; container.push(data); let index = container.length - 1; while (index) { let parent = Math.floor((index - 1) / 2); if (!cmp(container[index], container[parent])) { return; } swap(container, index, parent); index = parent; } } extract() { const { container, cmp } = this; if (!container.length) { return null; } swap(container, 0, container.length - 1); const res = container.pop(); const length = container.length; let index = 0, exchange = index * 2 + 1; while (exchange < length) { // 若是有右節點,而且右節點的值大於左節點的值 let right = index * 2 + 2; if (right < length && cmp(container[right], container[exchange])) { exchange = right; } if (!cmp(container[exchange], container[index])) { break; } swap(container, exchange, index); index = exchange; exchange = index * 2 + 1; } return res; } top() { if (this.container.length) return this.container[0]; return null; } } /** * @param {number} n * @return {number} */ var nthUglyNumber = function(n) { const heap = new Heap((x, y) => x < y); const res = new Array(n); const map = {}; const primes = [2, 3, 5]; heap.insert(1); map[1] = true; for (let i = 0; i < n; ++i) { res[i] = heap.extract(); for (const prime of primes) { let tmp = res[i] * prime; if (!map[tmp]) { heap.insert(tmp); map[tmp] = true; } } } return res[n - 1]; };
時間複雜度是\(O(NlogN)\), 空間複雜度是\(O(N)\)。spa
整理不易,若對您有幫助,請給個「關注+點贊」,您的支持是我更新的動力 👇指針