Given a list of prices for n products, find the minimum amount a customer needs to spend to obtain a gift card. A gift card is awarded when a customer purchases a contiguous subsegment of products, and at least two products within that subsegment have matching prices. If it's not possible for any customer to receive a gift card, return -1.
Examples:
Input: prices[] = [1, 2, 3, 1, 2, 1]
Output: 4
Explanation: Buying products from index 3 to 5, which includes products [1, 2, 1]. Two of these products have a matching price.Input: prices[] = [1, 2, 1, 2]
Output: 4
Explanation: Buying products from index 0 to 3, which includes products [1, 2, 1]. Two of these products have a matching price.
Input: prices[] = [1, 100, 1, 7, 7]
Output: 14
Explanation: Buying products from index 3 to 4, which includes products [7, 7]. Two of these products have a matching price.
Approach: To solve the problem follow the below idea:
Find prefix sum of prices and then identify the indices of products with matching prices
Steps to solve the problem:
- First, Calculate prefix sum of prices and store it in prefix_sum vector.
- Use unordered_map to store indices of products with the same price
- Declare constants INF and res for calculating minimum price.
- Now loop through these indices, comparing pairs to identify contiguous subsegments.
- For each pair of indices, we first calculate the cost by subtracting the prefix sum at the left index from the prefix sum at the right index.
- The minimum cost among all subsegments is updated in res.
- After the loops, if res remains as "infinity," it returns -1, Otherwise, it returns the minimum cost calculated.
Below is the implementation of the approach:
// C++ code for the above approach:
#include <climits>
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
int findMinimumPrice(vector<int> price)
{
int n = price.size();
vector<long long> prefix_sum(n, 0);
for (int i = 0; i < n; i++) {
if (i - 1 >= 0) {
prefix_sum[i] += prefix_sum[i - 1];
}
prefix_sum[i] += price[i];
}
unordered_map<int, vector<int> > idxs;
for (int i = 0; i < n; i++) {
idxs[price[i]].push_back(i);
}
long long INF = LLONG_MAX;
long long res = INF;
for (const auto& pair : idxs) {
int key = pair.first;
vector<int> value = pair.second;
int m = value.size();
for (int i = 0; i < m; i++) {
if (i + 1 < m) {
int left_index = value[i];
int right_index = value[i + 1];
res = min(
res,
prefix_sum[right_index]
- (left_index - 1 >= 0
? prefix_sum[left_index - 1]
: 0));
}
}
}
return res == INF ? -1 : static_cast<int>(res);
}
// Drivers code
int main()
{
vector<int> prices = { 1, 3, 2, 2, 2, 3 };
int minPrice = findMinimumPrice(prices);
// Function Call
if (minPrice == -1) {
cout << "No minimum price found." << endl;
}
else {
cout << "Minimum price: " << minPrice << endl;
}
return 0;
}
// Java code for the above approach
import java.util.*;
class GFG {
public static int findMinimumPrice(List<Integer> price)
{
int n = price.size();
List<Long> prefixSum = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (i - 1 >= 0) {
prefixSum.add(prefixSum.get(i - 1)
+ price.get(i));
}
else {
prefixSum.add((long)price.get(i));
}
}
Map<Integer, List<Integer> > idxs = new HashMap<>();
for (int i = 0; i < n; i++) {
int value = price.get(i);
if (!idxs.containsKey(value)) {
idxs.put(value, new ArrayList<>());
}
idxs.get(value).add(i);
}
long INF = Long.MAX_VALUE;
long res = INF;
for (Map.Entry<Integer, List<Integer> > entry :
idxs.entrySet()) {
int key = entry.getKey();
List<Integer> value = entry.getValue();
int m = value.size();
for (int i = 0; i < m; i++) {
if (i + 1 < m) {
int leftIndex = value.get(i);
int rightIndex = value.get(i + 1);
res = Math.min(
res, prefixSum.get(rightIndex)
- (leftIndex - 1 >= 0
? prefixSum.get(
leftIndex - 1)
: 0));
}
}
}
return res == INF ? -1 : (int)res;
}
public static void main(String[] args)
{
List<Integer> prices
= Arrays.asList(1, 3, 2, 2, 2, 3);
int minPrice = findMinimumPrice(prices);
// Function Call
if (minPrice == -1) {
System.out.println("No minimum price found.");
}
else {
System.out.println("Minimum price: "
+ minPrice);
}
}
}
// This code is contributed by Abhinav Mahajan
// (abhinav_m22).
def find_minimum_price(prices):
n = len(prices)
prefix_sum = [0] * n
# Calculate the prefix sum of prices
for i in range(n):
if i - 1 >= 0:
prefix_sum[i] = prefix_sum[i - 1] + prices[i]
else:
prefix_sum[i] = prices[i]
# Create a dictionary to store indices of each price
idxs = {}
for i in range(n):
value = prices[i]
if value not in idxs:
idxs[value] = []
idxs[value].append(i)
INF = float('inf')
res = INF
# Iterate through the dictionary entries
for key, value in idxs.items():
m = len(value)
# Iterate through the indices of each price
for i in range(m - 1):
left_index = value[i]
right_index = value[i + 1]
res = min(res, prefix_sum[right_index] -
(prefix_sum[left_index - 1] if left_index - 1 >= 0 else 0))
return -1 if res == INF else int(res)
# Driver code
prices = [1, 3, 2, 2, 2, 3]
min_price = find_minimum_price(prices)
# Function Call
if min_price == -1:
print("No minimum price found.")
else:
print("Minimum price:", min_price)
using System;
using System.Collections.Generic;
using System.Linq;
class GFG
{
public static int FindMinimumPrice(List<int> prices)
{
int n = prices.Count;
List<long> prefixSum = new List<long>();
for (int i = 0; i < n; i++)
{
if (i - 1 >= 0)
{
prefixSum.Add(prefixSum[i - 1] + prices[i]);
}
else
{
prefixSum.Add(prices[i]);
}
}
Dictionary<int, List<int>> idxs = new Dictionary<int, List<int>>();
for (int i = 0; i < n; i++)
{
int value = prices[i];
if (!idxs.ContainsKey(value))
{
idxs[value] = new List<int>();
}
idxs[value].Add(i);
}
long INF = long.MaxValue;
long res = INF;
foreach (var entry in idxs)
{
int key = entry.Key;
List<int> value = entry.Value;
int m = value.Count;
for (int i = 0; i < m; i++)
{
if (i + 1 < m)
{
int leftIndex = value[i];
int rightIndex = value[i + 1];
res = Math.Min(res, prefixSum[rightIndex] - (leftIndex - 1 >= 0 ? prefixSum[leftIndex - 1] : 0));
}
}
}
return res == INF ? -1 : (int)res;
}
public static void Main()
{
List<int> prices = new List<int> {1, 3, 2, 2, 2, 3};
int minPrice = FindMinimumPrice(prices);
// Function Call
if (minPrice == -1)
{
Console.WriteLine("No minimum price found.");
}
else
{
Console.WriteLine($"Minimum price: {minPrice}");
}
}
}
// This code is contributed by Rohit Singh
function findMinimumPrice(price) {
const n = price.length;
const prefixSum = Array(n).fill(0);
for (let i = 0; i < n; i++) {
if (i - 1 >= 0) {
prefixSum[i] += prefixSum[i - 1];
}
prefixSum[i] += price[i];
}
const idxs = new Map();
for (let i = 0; i < n; i++) {
if (!idxs.has(price[i])) {
idxs.set(price[i], []);
}
idxs.get(price[i]).push(i);
}
const INF = Number.MAX_SAFE_INTEGER;
let res = INF;
for (const [key, value] of idxs) {
const m = value.length;
for (let i = 0; i < m; i++) {
if (i + 1 < m) {
const leftIndex = value[i];
const rightIndex = value[i + 1];
res = Math.min(
res,
prefixSum[rightIndex] - (leftIndex - 1 >= 0 ? prefixSum[leftIndex - 1] : 0)
);
}
}
}
return res === INF ? -1 : res;
}
// Driver code
const prices = [1, 3, 2, 2, 2, 3];
const minPrice = findMinimumPrice(prices);
// Function Call
if (minPrice === -1) {
console.log("No minimum price found.");
} else {
console.log("Minimum price:", minPrice);
}
Output
Minimum price: 4
Time Complexity: O(n), where n is the number of products.
Auxiliary Space: O(n + m), where n is the number of products, and m is the number of unique product prices.