題目連結:
題目意譯:
你被給定一個索引值從 0 開始的整數陣列 nums。在一次操作中你可以將任意一個元素替換成任兩個其值相加等於它的元素。
例如,考慮 nums = [5,6,7]。在一次操作中,我們可以把 nums[i] 替換成 2 和 4,而此時 nums 變成了 [5,2,4,7]。
回傳最少所需的操作數來將 nums 變成一個以非遞減順序排序的陣列。
限制:
1 ≦ nums.length ≦ 10 ^ 5
1 ≦ nums[i] ≦ 10 ^ 9
範例測資:
範例 1:
輸入: nums = [3,9,3]
輸出: 2
解釋: 以下是將陣列變成非遞減順序的步驟:
- 從 [3,9,3],將 9 替換成 3 和 6,因此陣列變成 [3,3,6,3]
- 從 [3,3,6,3],將 6 替換成 3 和 3,因此陣列變成 [3,3,3,3,3]
將陣列變成非遞減順序的步驟是 2 步。因此我們回傳 2。
範例 2:
輸入: nums = [1,2,3,4,5]
輸出: 0
解釋: 該陣列已經是非遞減的順序。因此我們回傳 0。
解題思維:
由於我們不能改變這些元素的順序本身,只能新增若干元素其由原先某元素拆解而得,因此可以看到最後一個元素不需要拆解(拆解只會浪費而已,因為前一個(即倒數第二個)元素也需要配合它,而本來可能不需要)。
因此我們可以從最後一個元素往回看到第一個元素:
假設前一個看到的元素之值為 L(如果是最後一個元素,則 L 設為無限大),而現在看到的元素之值為 X。
如果 X ≦ L,則不需要做任何操作;
而如果 X > L,則我們需要將 X 拆解成 P1 、 P2 、……、 Pk,其中 P1 + P1 + …… + Pk 且 P1 ≦ P2 ≦ …… ≦ Pk ≦ L。而我們要盡可能地讓 P1 大(為了讓下一個元素拆解次數少一點)還要讓 k 盡量小(讓現在的元素拆解次數少一點)。
我們先讓當前拆解次數盡可能小,因此 k 應為
X ÷ L
如果 X 可以被 L 整除的話;反之則應為
X ÷ L 並無條件進位
接著把 P1 變得盡可能大,則當 X 可以被 L 整除時,其值應為
L
反之,其應為
X ÷ k 取整數部分
因此每一個元素都這麼做後,我們便可以把總操作數最小化,因此過程中統計操作數最後便可以得到所求。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。