題意
給定一個長度為 n n n 的整數陣列 n u m s nums n u m s ,以及兩個非負整數 i n d e x D i f f e r e n c e indexDifference in d e x D i ff ere n ce 和 v a l u e D i f f e r e n c e valueDifference v a l u eD i ff ere n ce 。
找出兩個下標 i i i 和 j j j ,滿足以下條件:
a b s ( i − j ) ≥ i n d e x D i f f e r e n c e abs(i - j) \geq indexDifference ab s ( i − j ) ≥ in d e x D i ff ere n ce
a b s ( n u m s [ i ] − n u m s [ j ] ) ≥ v a l u e D i f f e r e n c e abs(nums[i] - nums[j]) \geq valueDifference ab s ( n u m s [ i ] − n u m s [ j ]) ≥ v a l u eD i ff ere n ce
如果存在這樣的下標,則返回 [ i , j ] [i, j] [ i , j ] ;否則返回 [ − 1 , − 1 ] [-1, -1] [ − 1 , − 1 ] 。
注意:i i i 和 j j j 可以相等。
限制
1 ≤ n = = n u m s . l e n g t h ≤ 100 1 \leq n == nums.length \leq 100 1 ≤ n == n u m s . l e n g t h ≤ 100
0 ≤ n u m s [ i ] ≤ 50 0 \leq nums[i] \leq 50 0 ≤ n u m s [ i ] ≤ 50
0 ≤ i n d e x D i f f e r e n c e ≤ 100 0 \leq indexDifference \leq 100 0 ≤ in d e x D i ff ere n ce ≤ 100
0 ≤ v a l u e D i f f e r e n c e ≤ 50 0 \leq valueDifference \leq 50 0 ≤ v a l u eD i ff ere n ce ≤ 50
思路
解法一:暴力法(Brute Force)
由限制可以看出數據範圍不大,因此可以直接暴力枚舉所有可能的下標對 ( i , j ) (i, j) ( i , j ) ,檢查是否滿足條件。
此外,在枚舉 j j j 時,可以從 i + i n d e x D i f f e r e n c e i + indexDifference i + in d e x D i ff ere n ce 開始遞減,這樣可以保證 j − i ≥ i n d e x D i f f e r e n c e j - i \geq indexDifference j − i ≥ in d e x D i ff ere n ce ,因此可以減少一些不必要的枚舉,且檢查是否滿足條件時,只需檢查 a b s ( n u m s [ i ] − n u m s [ j ] ) ≥ v a l u e D i f f e r e n c e abs(nums[i] - nums[j]) \geq valueDifference ab s ( n u m s [ i ] − n u m s [ j ]) ≥ v a l u eD i ff ere n ce 即可。
複雜度分析
時間複雜度:O ( n 2 ) O(n^2) O ( n 2 ) ,其中 n n n 為陣列 n u m s nums n u m s 的長度。
空間複雜度:O ( 1 ) O(1) O ( 1 ) 。
1 2 3 4 5 6 7 8 class Solution : def findIndices (self, nums: List [int ], indexDifference: int , valueDifference: int ) -> List [int ]: n = len (nums) for i in range (n): for j in range (i + indexDifference, n): if abs (nums[i]-nums[j]) >= valueDifference: return [i,j] return [-1 ,-1 ]
1 2 3 4 5 6 7 8 9 10 11 class Solution {public : vector<int > findIndices (vector<int >& nums, int indexDifference, int valueDifference) { int n = nums.size (); for (int i = 0 ; i < n; i++) for (int j = i + indexDifference; j < n; j++) if (abs (nums[j] - nums[i]) >= valueDifference) return {i, j}; return {-1 , -1 }; } };
解法二:雙指標(Two Pointers)
類似於解法一中的優化,在枚舉右指針 j j j 時,只檢查一個左指針 i = j − i n d e x D i f f e r e n c e i = j - indexDifference i = j − in d e x D i ff ere n ce ,這樣可以保證 j − i = i n d e x D i f f e r e n c e j - i = indexDifference j − i = in d e x D i ff ere n ce ,且對於之前檢查過的 i p r e i_{pre} i p re ,也能夠滿足此條件。故我們必須在枚舉 j j j 時,利用與其對應的 i i i ,來檢查 n u m s [ : i + 1 ] nums[:i+1] n u m s [ : i + 1 ] 中是否存在某個數字能夠與 j j j 構成答案,為此我們需要維護 n u m s [ : i + 1 ] nums[:i+1] n u m s [ : i + 1 ] 中的某些性質。
而若當前枚舉的 j j j 存在答案,則根據限制條件,答案在 n u m s [ : i + 1 ] nums[:i+1] n u m s [ : i + 1 ] 中,且其中的最大值或最小值必定也能成為答案,證明如下:
若存在下標 k k k ,其中 0 ≤ k ≤ i 0 \leq k \leq i 0 ≤ k ≤ i 使得 [ k , j ] [k, j] [ k , j ] 滿足 n u m s [ k ] − n u m s [ j ] ≥ v a l u e D i f f e r e n c e nums[k] - nums[j] \geq valueDifference n u m s [ k ] − n u m s [ j ] ≥ v a l u eD i ff ere n ce ,則因為 n u m s [ i d x m a x ] ≥ n u m s [ k ] nums[idx_{max}] \geq nums[k] n u m s [ i d x ma x ] ≥ n u m s [ k ] ,故 [ i d x m a x , j ] [idx_{max}, j] [ i d x ma x , j ] 也滿足條件。
若存在下標 k k k ,其中 0 ≤ k ≤ i 0 \leq k \leq i 0 ≤ k ≤ i 使得 [ k , j ] [k, j] [ k , j ] 滿足 n u m s [ j ] − n u m s [ k ] ≥ v a l u e D i f f e r e n c e nums[j] - nums[k] \geq valueDifference n u m s [ j ] − n u m s [ k ] ≥ v a l u eD i ff ere n ce ,則因為 n u m s [ i d x m i n ] ≤ n u m s [ k ] nums[idx_{min}] \leq nums[k] n u m s [ i d x min ] ≤ n u m s [ k ] ,故 [ i d x m i n , j ] [idx_{min}, j] [ i d x min , j ] 也滿足條件。
因此可以維護 n u m s [ i + 1 ] nums[i+1] n u m s [ i + 1 ] 中最大值和最小值的 index,並在枚舉 j j j 時同時更新,更新後只需檢查 [ i d x m a x , j ] [idx_{max}, j] [ i d x ma x , j ] 和 [ i d x m i n , , j ] [idx_{min},, j] [ i d x min ,, j ] 是否滿足條件即可。
複雜度分析
時間複雜度:O ( n ) O(n) O ( n ) ,其中 n n n 為陣列 n u m s nums n u m s 的長度。
空間複雜度:O ( 1 ) O(1) O ( 1 ) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution : def findIndices (self, nums: List [int ], indexDifference: int , valueDifference: int ) -> List [int ]: n = len (nums) max_idx = min_idx = 0 for j in range (indexDifference, n): i = j - indexDifference if nums[i] > nums[max_idx]: max_idx = i elif nums[i] < nums[min_idx]: min_idx = i if nums[max_idx] - nums[j] >= valueDifference: return [max_idx, j] if nums[j] - nums[min_idx] >= valueDifference: return [min_idx, j] return [-1 , -1 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution {public : vector<int > findIndices (vector<int >& nums, int indexDifference, int valueDifference) { int n = nums.size (), max_idx = 0 , min_idx = 0 ; for (int j = indexDifference; j < n; j++){ int i = j - indexDifference; if (nums[i] > nums[max_idx]) max_idx = i; else if (nums[i] < nums[min_idx]) min_idx = i; if (nums[max_idx] - nums[j] >= valueDifference) return {max_idx, j}; else if (nums[j] - nums[min_idx] >= valueDifference) return {min_idx, j}; } return {-1 , -1 }; } };
寫在最後
Cover photo is generated by @たろたろ , thanks for their work!
這題存在數據範圍更大的版本,即 2905. Find Indices With Index and Value Difference II ,只能使用方法二解決。