Welcome to Subscribe On Youtube

3119. Maximum Number of Potholes That Can Be Fixed 🔒

Description

You are given a string road, consisting only of characters "x" and ".", where each "x" denotes a pothole and each "." denotes a smooth road, and an integer budget.

In one repair operation, you can repair n consecutive potholes for a price of n + 1.

Return the maximum number of potholes that can be fixed such that the sum of the prices of all of the fixes doesn't go over the given budget.

 

Example 1:

Input: road = "..", budget = 5

Output: 0

Explanation:

There are no potholes to be fixed.

Example 2:

Input: road = "..xxxxx", budget = 4

Output: 3

Explanation:

We fix the first three potholes (they are consecutive). The budget needed for this task is 3 + 1 = 4.

Example 3:

Input: road = "x.x.xxx...x", budget = 14

Output: 6

Explanation:

We can fix all the potholes. The total cost would be (1 + 1) + (1 + 1) + (3 + 1) + (1 + 1) = 10 which is within our budget of 14.

 

Constraints:

  • 1 <= road.length <= 105
  • 1 <= budget <= 105 + 1
  • road consists only of characters '.' and 'x'.

Solutions

Solution 1: Counting + Greedy

First, we count the number of each continuous pothole, recorded in the array $cnt$, i.e., $cnt[k]$ represents there are $cnt[k]$ continuous potholes of length $k$.

Since we want to repair as many potholes as possible, and for a continuous pothole of length $k$, we need to spend a cost of $k + 1$, we should prioritize repairing longer potholes to minimize the cost.

Therefore, we start repairing from the longest pothole. For a pothole of length $k$, the maximum number we can repair is $t = \min(\text{budget} / (k + 1), \text{cnt}[k])$. We add the number of repairs multiplied by the length $k$ to the answer, then update the remaining budget. For the remaining $cnt[k] - t$ potholes of length $k$, we merge them into the potholes of length $k - 1$. Continue this process until all potholes are traversed.

The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $road$.

  • class Solution {
        public int maxPotholes(String road, int budget) {
            road += ".";
            int n = road.length();
            int[] cnt = new int[n];
            int k = 0;
            for (char c : road.toCharArray()) {
                if (c == 'x') {
                    ++k;
                } else if (k > 0) {
                    ++cnt[k];
                    k = 0;
                }
            }
            int ans = 0;
            for (k = n - 1; k > 0 && budget > 0; --k) {
                int t = Math.min(budget / (k + 1), cnt[k]);
                ans += t * k;
                budget -= t * (k + 1);
                cnt[k - 1] += cnt[k] - t;
            }
            return ans;
        }
    }
    
  • class Solution {
    public:
        int maxPotholes(string road, int budget) {
            road.push_back('.');
            int n = road.size();
            vector<int> cnt(n);
            int k = 0;
            for (char& c : road) {
                if (c == 'x') {
                    ++k;
                } else if (k) {
                    ++cnt[k];
                    k = 0;
                }
            }
            int ans = 0;
            for (k = n - 1; k && budget; --k) {
                int t = min(budget / (k + 1), cnt[k]);
                ans += t * k;
                budget -= t * (k + 1);
                cnt[k - 1] += cnt[k] - t;
            }
            return ans;
        }
    };
    
  • class Solution:
        def maxPotholes(self, road: str, budget: int) -> int:
            road += "."
            n = len(road)
            cnt = [0] * n
            k = 0
            for c in road:
                if c == "x":
                    k += 1
                elif k:
                    cnt[k] += 1
                    k = 0
            ans = 0
            for k in range(n - 1, 0, -1):
                if cnt[k] == 0:
                    continue
                t = min(budget // (k + 1), cnt[k])
                ans += t * k
                budget -= t * (k + 1)
                if budget == 0:
                    break
                cnt[k - 1] += cnt[k] - t
            return ans
    
    
  • func maxPotholes(road string, budget int) (ans int) {
    	road += "."
    	n := len(road)
    	cnt := make([]int, n)
    	k := 0
    	for _, c := range road {
    		if c == 'x' {
    			k++
    		} else if k > 0 {
    			cnt[k]++
    			k = 0
    		}
    	}
    	for k = n - 1; k > 0 && budget > 0; k-- {
    		t := min(budget/(k+1), cnt[k])
    		ans += t * k
    		budget -= t * (k + 1)
    		cnt[k-1] += cnt[k] - t
    	}
    	return
    }
    
  • function maxPotholes(road: string, budget: number): number {
        road += '.';
        const n = road.length;
        const cnt: number[] = Array(n).fill(0);
        let k = 0;
        for (const c of road) {
            if (c === 'x') {
                ++k;
            } else if (k) {
                ++cnt[k];
                k = 0;
            }
        }
        let ans = 0;
        for (k = n - 1; k && budget; --k) {
            const t = Math.min(Math.floor(budget / (k + 1)), cnt[k]);
            ans += t * k;
            budget -= t * (k + 1);
            cnt[k - 1] += cnt[k] - t;
        }
        return ans;
    }
    
    
  • public class Solution {
        public int MaxPotholes(string road, int budget) {
            road += '.';
            int n = road.Length;
            int[] cnt = new int[n];
            int k = 0;
            foreach (char c in road) {
                if (c == 'x') {
                    ++k;
                } else if (k > 0) {
                    ++cnt[k];
                    k = 0;
                }
            }
            int ans = 0;
            for (k = n - 1; k > 0 && budget > 0; --k) {
                int t = Math.Min(budget / (k + 1), cnt[k]);
                ans += t * k;
                budget -= t * (k + 1);
                cnt[k - 1] += cnt[k] - t;
            }
            return ans;
        }
    }
    
  • impl Solution {
        pub fn max_potholes(road: String, budget: i32) -> i32 {
            let mut cs: Vec<char> = road.chars().collect();
            cs.push('.');
            let n = cs.len();
            let mut cnt: Vec<i32> = vec![0; n];
            let mut k = 0;
    
            for c in cs.iter() {
                if *c == 'x' {
                    k += 1;
                } else if k > 0 {
                    cnt[k] += 1;
                    k = 0;
                }
            }
    
            let mut ans = 0;
            let mut budget = budget;
    
            for k in (1..n).rev() {
                if budget == 0 {
                    break;
                }
                let t = std::cmp::min(budget / ((k as i32) + 1), cnt[k]);
                ans += t * (k as i32);
                budget -= t * ((k as i32) + 1);
                cnt[k - 1] += cnt[k] - t;
            }
    
            ans
        }
    }
    
    

All Problems

All Solutions