【LeetCode - 798】得分最高的最小轮调(转化法)
解題報告:
思路一:這題首先說一個nlogn的方法。
首先一個主客轉化,題目描述是說把數組做翻轉,idx不變,然后nums[i]和i作比較。那么我們可以轉化為讓數組不變,idx轉變,即:假設剛開始i=4,那么idx的變化為[4,3,2,1,0,n-1,...,5],再用nums[i] -? idx,如果這個值>0,則是符合區間的k。具體來說,比如
nums = [ 2, 3, 1, 4, 0],對應的idx idx = [ 0, 1, 2, 3, 4],作差后 diff = [-2,-2, 1,-1, 4],此時k=0,然后移動一次的話,diff變為 diff = [ 2,-3, 0,-2, 3],此時k=1, diff = [ 1, 1,-1,-3, 2],此時k=2, diff = [ 0, 0, 3,-4, 1],此時k=3,即,不難發現,每次k變化的時候的時候,對應的就是全數組-1,然后在第k-1的位置上+n。
然后數組中>=0的元素個數就是k輪調的時候的答案。
因此我們需要,區間更新,單點更新嗎,區間查詢,這三個操作,可以用線段樹維護,因而復雜度是nlogn。
思路二:
可以有兩種方法過渡到思路二:
其一:剛剛的方法一直是在數組上做文章,即固定數組是不變的,然后變化k,來維護答案。那可否考慮直接從k上做文章,因為k最多就1e5,建立一個k的數組,我們直接考慮對于數組中的每個元素,會影響到哪些k值,做對應的更新。
其二:之前的想法是對于每一個k,遍歷所有的元素找出對應答案。那么也可以對于每一個元素,考慮他會對哪些k產生影響,然后直接從k數組中維護,因此可以建立一個k數組。
綜上,我們可以考慮每一個k,用類似數形結合的方法,可以方便的發現,當i<nums[i]時,k數組中只 有一段區間需要更新,當i>=nums[i]時,k數組中有兩段區間需要更新。
這種思路還有一個好處就是,我們不需要動態更新和查詢答案了。我們只需要記錄每個元素對答案的影響,然后最后對答案數組查詢一次就行了。
因此我們需要,區間更新,區間查詢一次。因此我們不需要線段樹了,可以用差分數組代替。
這種思路的轉換還是很妙的,記錄一下。
AC代碼:(思路二的解法)
class Solution { public:int num[200005];int bestRotation(vector<int>& nums) {int n = nums.size();for(int i = 0; i<n; i++) {if(i >= nums[i]) {int l = 0, r = i-nums[i];int ll = r + nums[i]+1, rr = n-1;num[l]++; num[ll]++;num[r+1]--; num[rr+1]--;}else {int l = i+1, r = l1+(n-nums[i]-1);num[l]++;num[r+1]--;}}for(int i = 1; i<n; i++) {num[i] += num[i-1];}int ans = 0;for(int i = 0; i<n; i++) {if(num[i] > num[ans]) {ans = i;}}return ans;} };?
總結
以上是生活随笔為你收集整理的【LeetCode - 798】得分最高的最小轮调(转化法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线程池简单实现java_简单实现java
- 下一篇: 招行信用卡账单分期占用额度吗 账单分期后