You are given an integer array prices
representing the daily price history of a stock, where prices[i]
is the stock price on the ith
day.
A smooth descent period of a stock consists of one or more contiguous days such that the price on each day is lower than the price on the preceding day by exactly 1
. The first day of the period is exempted from this rule.
Return the number of smooth descent periods.
Example 1:
Input: prices = [3,2,1,4] Output: 7 Explanation: There are 7 smooth descent periods: [3], [2], [1], [4], [3,2], [2,1], and [3,2,1] Note that a period with one day is a smooth descent period by the definition.
Example 2:
Input: prices = [8,6,7,7] Output: 4 Explanation: There are 4 smooth descent periods: [8], [6], [7], and [7] Note that [8,6] is not a smooth descent period as 8 - 6 ≠ 1.
Example 3:
Input: prices = [1] Output: 1 Explanation: There is 1 smooth descent period: [1]
Constraints:
1 <= prices.length <= 105
1 <= prices[i] <= 105
The problem asks to find the number of smooth descent periods in a given array of stock prices. A smooth descent period is defined as one or more contiguous days where the price on each day is exactly 1 lower than the price on the preceding day (except for the first day).
The most efficient approach to solve this problem is using a two-pointer technique. This avoids nested loops, resulting in a linear time complexity solution.
Algorithm:
Initialization:
ans
: A variable to store the total count of smooth descent periods, initialized to 0.i
: A pointer representing the start of a smooth descent period. Starts at index 0.j
: A pointer representing the end of a smooth descent period. Starts at index 0.Iteration:
prices
array using pointer i
.j
) finds the end of the current smooth descent period. It continues as long as j
is within the array bounds and the difference between consecutive prices is exactly 1 (prices[j - 1] - prices[j] == 1
).cnt = j - i
: Calculates the length of the current smooth descent period.ans += (1 + cnt) * cnt // 2
: Adds the number of smooth descent periods found within this segment to ans
. The formula (1 + cnt) * cnt // 2
represents the sum of integers from 1 to cnt
(representing the number of sub-periods within the current period). Integer division (//
) is used to handle potential integer overflow in certain programming languages.i = j
: Moves i
to the beginning of the next smooth descent period.Return Value:
ans
, which is the total number of smooth descent periods.Time Complexity: O(n) - The algorithm iterates through the prices
array once. The inner loop only advances j
until it finds the end of a smooth descent period, ensuring linear time complexity overall.
Space Complexity: O(1) - The algorithm uses a constant amount of extra space regardless of the input size.
The code implementations provided in the original response are already well-structured and efficient. I'll present them again here for clarity:
Python3:
class Solution:
def getDescentPeriods(self, prices: List[int]) -> int:
ans = 0
i, n = 0, len(prices)
while i < n:
j = i + 1
while j < n and prices[j - 1] - prices[j] == 1:
j += 1
cnt = j - i
ans += (1 + cnt) * cnt // 2
i = j
return ans
Java:
class Solution {
public long getDescentPeriods(int[] prices) {
long ans = 0;
int n = prices.length;
for (int i = 0, j = 0; i < n; i = j) {
j = i + 1;
while (j < n && prices[j - 1] - prices[j] == 1) {
++j;
}
int cnt = j - i;
ans += (1L + cnt) * cnt / 2;
}
return ans;
}
}
C++:
class Solution {
public:
long long getDescentPeriods(vector<int>& prices) {
long long ans = 0;
int n = prices.size();
for (int i = 0, j = 0; i < n; i = j) {
j = i + 1;
while (j < n && prices[j - 1] - prices[j] == 1) {
++j;
}
int cnt = j - i;
ans += (1LL + cnt) * cnt / 2;
}
return ans;
}
};
Go:
func getDescentPeriods(prices []int) (ans int64) {
n := len(prices)
for i, j := 0, 0; i < n; i = j {
j = i + 1
for j < n && prices[j-1]-prices[j] == 1 {
j++
}
cnt := j - i
ans += int64((1 + cnt) * cnt / 2)
}
return
}
TypeScript:
function getDescentPeriods(prices: number[]): number {
let ans = 0;
const n = prices.length;
for (let i = 0, j = 0; i < n; i = j) {
j = i + 1;
while (j < n && prices[j - 1] - prices[j] === 1) {
++j;
}
const cnt = j - i;
ans += Math.floor(((1 + cnt) * cnt) / 2);
}
return ans;
}
These codes all implement the same algorithm with minor syntactic differences based on the language. They all achieve the optimal O(n) time complexity and O(1) space complexity.