以长度为 K 的最大跳跃到达数组末尾的最小成本
给定一个大小为N的数组arr[]和一个整数K ,可以从索引i移动到任何其他索引j ,使得j ≤ i+k 。处于任何索引“ i ”的成本是arr[i] 。任务是找到从索引0开始到达数组末尾的最小成本。
例子:
Input : arr[] = {2, 4, 1, 6, 3}, K = 2
Output: 6
Explanation: Path can be taken as 2 -> 1-> 3 = 6
Input: arr[] = {1, 2, 3, 4, 5, 6}, K = 3
Output: 10
Explanation: Path can be taken as 1->3->6 = 10
天真的方法:可以使用动态规划来解决该任务。维护一个dp[]数组,其中 dp[i] 表示到达第i 个索引所需的最小成本。请按照以下步骤解决问题:
- 从当前元素向后遍历所有K个元素,找到最小dp值并将其添加到当前答案中。
- 因此,计算第 i 个索引的答案将是dp[i] = arr[i] + min(dp[j]对于所有 j 使得ik <= j < i ) 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the minimum jumps
int solve(vector& arr, int K)
{
int size = arr.size();
vector dp(size, 0);
// Initially only a single element
dp[0] = arr[0];
for (int idx = 1; idx < size; idx++) {
// At most k elements backwards
int end = max(-1, idx - K - 1);
int mini = INT_MAX;
// Find minimum among all the values
for (int ptr = idx - 1; ptr > end; ptr--) {
mini = min(mini, dp[ptr]);
}
dp[idx] = arr[idx] + mini;
}
// Return cost to reach the
// last index of array
return dp[size - 1];
}
// Driver Code
int main()
{
vector arr = { 2, 4, 1, 6, 3 };
int K = 2;
int ans = solve(arr, K);
cout << ans << "\n";
}
// This code is contributed by Taranpreet
Java
// Java program for the above approach
class GFG {
// Function to find the minimum jumps
static int solve(int[] arr, int K) {
int size = arr.length;
int[] dp = new int[size];
for (int i = 0; i < size; i++) {
dp[i] = 0;
}
// Initially only a single element
dp[0] = arr[0];
for (int idx = 1; idx < size; idx++) {
// At most k elements backwards
int end = Math.max(-1, idx - K - 1);
int mini = Integer.MAX_VALUE;
// Find minimum among all the values
for (int ptr = idx - 1; ptr > end; ptr--) {
mini = Math.min(mini, dp[ptr]);
}
dp[idx] = arr[idx] + mini;
}
// Return cost to reach the
// last index of array
return dp[size - 1];
}
// Driver Code
public static void main(String args[]) {
int[] arr = { 2, 4, 1, 6, 3 };
int K = 2;
int ans = solve(arr, K);
System.out.println(ans);
}
}
// This code is contributed by Saurabh Jaiswal
Python3
# Python program for the above approach
# Function to find the minimum jumps
def solve(arr, K):
size = len(arr)
dp = [0] * (size)
# Initially only a single element
dp[0] = arr[0]
for idx in range(1, size, 1):
# At most k elements backwards
end = max(-1, idx - K - 1)
mini = float('inf')
# Find minimum among all the values
for ptr in range(idx - 1, end, -1):
mini = min(mini, dp[ptr])
dp[idx] = arr[idx] + mini
# Return cost to reach the
# last index of array
return (dp[-1])
# Driver Code
if __name__ == "__main__":
arr = [2, 4, 1, 6, 3]
K = 2
ans = solve(arr, K)
print(ans)
C#
// C# program for the above approach
using System;
class GFG
{
// Function to find the minimum jumps
static int solve(int []arr, int K)
{
int size = arr.Length;
int []dp = new int[size];
for(int i = 0; i < size; i++) {
dp[i] = 0;
}
// Initially only a single element
dp[0] = arr[0];
for (int idx = 1; idx < size; idx++) {
// At most k elements backwards
int end = Math.Max(-1, idx - K - 1);
int mini = Int32.MaxValue;
// Find minimum among all the values
for (int ptr = idx - 1; ptr > end; ptr--) {
mini = Math.Min(mini, dp[ptr]);
}
dp[idx] = arr[idx] + mini;
}
// Return cost to reach the
// last index of array
return dp[size - 1];
}
// Driver Code
public static void Main()
{
int []arr = { 2, 4, 1, 6, 3 };
int K = 2;
int ans = solve(arr, K);
Console.WriteLine(ans);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the minimum jumps
int solve(int arr[], int K, int size)
{
deque > ququ;
// Insert index and value
ququ.push_back({ 0, arr[0] });
for (int i = 1; i < size; i++) {
// Remove elements from front
// which are out of curr_window size
while ((ququ.size() > 0)
&& ((i - ququ.front().first) > K))
ququ.pop_front();
int curr_val = arr[i] + ququ.front().second;
// Pop greater elements from back
while ((ququ.size() > 0)
&& (curr_val <= ququ.back().second))
ququ.pop_back();
// Append index and curr_val
ququ.push_back({ i, curr_val });
}
// Finally return last value
// indicating cost to reach the last index
return ququ.back().second;
}
// driver code
int main()
{
int arr[] = { 2, 4, 1, 6, 3 };
int K = 2;
int size = sizeof(arr) / sizeof(arr[0]);
int ans = solve(arr, K, size);
cout << ans << endl;
return 0;
}
// This code is contributed by Palak Gupta
Python3
# Python program for the above approach
from collections import deque
# Function to find the minimum jumps
def solve(arr, K):
size = len(arr)
ququ = deque()
# Insert index and value
ququ.append((0, arr[0]))
for i in range(1, size, 1):
# Remove elements from front
# which are out of curr_window size
while(ququ and i - ququ[0][0] > K):
ququ.popleft()
curr_val = arr[i] + ququ[0][1]
# Pop greater elements from back
while(ququ and curr_val <= ququ[-1][1]):
ququ.pop()
# Append index and curr_val
ququ.append((i, curr_val))
# Finally return last value
# indicating cost to reach the last index
return ququ[-1][1]
# Driver Code
if __name__ == "__main__":
arr = [2, 4, 1, 6, 3]
K = 2
ans = solve(arr, K)
print(ans)
输出:
6
时间复杂度:O(N * K)
辅助空间:O(N)
高效方法:不是计算每个索引的最小成本,而是使用滑动窗口方法。使用大小为K的滑动窗口,使得最小元素始终出现在前面并保持排序顺序。请按照以下步骤解决问题:
- 初始化双端队列以保存数据,因为它支持从正面和背面弹出元素的高效操作。
- 在双端队列中插入第一个元素及其索引。还会插入索引以跟踪是否有任何元素在大小K的窗口限制内。
- 然后,从索引 1 开始循环直到数组的末尾。对于每个索引,从前面删除所有超出当前窗口大小的元素,即索引之间的差异> k。
- 将current_value计算为arr[i]和dequeue 的第一个值的总和。这里添加了第一个值,因为它是当前窗口中的最小值。
- 然后从 deque 中弹出所有值大于或等于 current_value 的元素。这样做是为了维护双端队列中的排序顺序。
- 最后返回双端队列中的最后一个值,显示到达数组最后一个索引的成本。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the minimum jumps
int solve(int arr[], int K, int size)
{
deque > ququ;
// Insert index and value
ququ.push_back({ 0, arr[0] });
for (int i = 1; i < size; i++) {
// Remove elements from front
// which are out of curr_window size
while ((ququ.size() > 0)
&& ((i - ququ.front().first) > K))
ququ.pop_front();
int curr_val = arr[i] + ququ.front().second;
// Pop greater elements from back
while ((ququ.size() > 0)
&& (curr_val <= ququ.back().second))
ququ.pop_back();
// Append index and curr_val
ququ.push_back({ i, curr_val });
}
// Finally return last value
// indicating cost to reach the last index
return ququ.back().second;
}
// driver code
int main()
{
int arr[] = { 2, 4, 1, 6, 3 };
int K = 2;
int size = sizeof(arr) / sizeof(arr[0]);
int ans = solve(arr, K, size);
cout << ans << endl;
return 0;
}
// This code is contributed by Palak Gupta
Python3
# Python program for the above approach
from collections import deque
# Function to find the minimum jumps
def solve(arr, K):
size = len(arr)
ququ = deque()
# Insert index and value
ququ.append((0, arr[0]))
for i in range(1, size, 1):
# Remove elements from front
# which are out of curr_window size
while(ququ and i - ququ[0][0] > K):
ququ.popleft()
curr_val = arr[i] + ququ[0][1]
# Pop greater elements from back
while(ququ and curr_val <= ququ[-1][1]):
ququ.pop()
# Append index and curr_val
ququ.append((i, curr_val))
# Finally return last value
# indicating cost to reach the last index
return ququ[-1][1]
# Driver Code
if __name__ == "__main__":
arr = [2, 4, 1, 6, 3]
K = 2
ans = solve(arr, K)
print(ans)
输出
6
时间复杂度:O(N)
辅助空间:O(N)