Welcome to Subscribe On Youtube

3510. Minimum Pair Removal to Sort Array II

Description

Given an array nums, you can perform the following operation any number of times:

  • Select the adjacent pair with the minimum sum in nums. If multiple such pairs exist, choose the leftmost one.
  • Replace the pair with their sum.

Return the minimum number of operations needed to make the array non-decreasing.

An array is said to be non-decreasing if each element is greater than or equal to its previous element (if it exists).

 

Example 1:

Input: nums = [5,2,3,1]

Output: 2

Explanation:

  • The pair (3,1) has the minimum sum of 4. After replacement, nums = [5,2,4].
  • The pair (2,4) has the minimum sum of 6. After replacement, nums = [5,6].

The array nums became non-decreasing in two operations.

Example 2:

Input: nums = [1,2,2]

Output: 0

Explanation:

The array nums is already sorted.

 

Constraints:

  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

Solutions

Solution 1

  • class Solution {
        record Pair(long s, int i) implements Comparable<Pair> {
            @Override
            public int compareTo(Pair other) {
                int compareS = Long.compare(this.s, other.s);
                return compareS != 0 ? compareS : Integer.compare(this.i, other.i);
            }
        }
    
        public int minimumPairRemoval(int[] nums) {
            int n = nums.length;
            int inv = 0;
            TreeSet<Pair> sl = new TreeSet<>();
            for (int i = 0; i < n - 1; ++i) {
                if (nums[i] > nums[i + 1]) {
                    ++inv;
                }
                sl.add(new Pair(nums[i] + nums[i + 1], i));
            }
            TreeSet<Integer> idx = new TreeSet<>();
            long[] arr = new long[n];
            for (int i = 0; i < n; ++i) {
                idx.add(i);
                arr[i] = nums[i];
            }
    
            int ans = 0;
            while (inv > 0) {
                ++ans;
                var p = sl.pollFirst();
                long s = p.s;
                int i = p.i;
                int j = idx.higher(i);
                if (arr[i] > arr[j]) {
                    --inv;
                }
                Integer h = idx.lower(i);
                if (h != null) {
                    if (arr[h] > arr[i]) {
                        --inv;
                    }
                    sl.remove(new Pair(arr[h] + arr[i], h));
                    if (arr[h] > s) {
                        ++inv;
                    }
                    sl.add(new Pair(arr[h] + s, h));
                }
                Integer k = idx.higher(j);
                if (k != null) {
                    if (arr[j] > arr[k]) {
                        --inv;
                    }
                    sl.remove(new Pair(arr[j] + arr[k], j));
                    if (s > arr[k]) {
                        ++inv;
                    }
                    sl.add(new Pair(s + arr[k], i));
                }
                arr[i] = s;
                idx.remove(j);
            }
            return ans;
        }
    }
    
    
  • class Solution {
    public:
        int minimumPairRemoval(vector<int>& nums) {
            int n = nums.size();
            int inv = 0;
    
            set<pair<long long, int>> sl;
            set<int> idx;
            vector<long long> arr(nums.begin(), nums.end());
    
            for (int i = 0; i < n; ++i) idx.insert(i);
    
            for (int i = 0; i < n - 1; ++i) {
                if (nums[i] > nums[i + 1]) {
                    ++inv;
                }
                sl.insert({(long long) nums[i] + nums[i + 1], i});
            }
    
            int ans = 0;
            while (inv > 0) {
                ++ans;
    
                auto it = sl.begin();
                long long s = it->first;
                int i = it->second;
                sl.erase(it);
    
                auto j_it = idx.upper_bound(i);
                int j = *j_it;
    
                if (arr[i] > arr[j]) {
                    --inv;
                }
    
                auto i_it = idx.find(i);
                if (i_it != idx.begin()) {
                    auto h_it = prev(i_it);
                    int h = *h_it;
    
                    if (arr[h] > arr[i]) {
                        --inv;
                    }
                    sl.erase({arr[h] + arr[i], h});
    
                    if (arr[h] > s) {
                        ++inv;
                    }
                    sl.insert({arr[h] + s, h});
                }
    
                auto k_it = next(j_it);
                if (k_it != idx.end()) {
                    int k = *k_it;
    
                    if (arr[j] > arr[k]) {
                        --inv;
                    }
                    sl.erase({arr[j] + arr[k], j});
    
                    if (s > arr[k]) {
                        ++inv;
                    }
                    sl.insert({s + arr[k], i});
                }
    
                arr[i] = s;
                idx.erase(j);
            }
    
            return ans;
        }
    };
    
    
  • class Solution:
        def minimumPairRemoval(self, nums: List[int]) -> int:
            n = len(nums)
            sl = SortedList()
            idx = SortedList(range(n))
            inv = 0
            for i in range(n - 1):
                sl.add((nums[i] + nums[i + 1], i))
                if nums[i] > nums[i + 1]:
                    inv += 1
            ans = 0
            while inv:
                ans += 1
                s, i = sl.pop(0)
                pos = idx.index(i)
                j = idx[pos + 1]
                if nums[i] > nums[j]:
                    inv -= 1
                if pos > 0:
                    h = idx[pos - 1]
                    if nums[h] > nums[i]:
                        inv -= 1
                    sl.remove((nums[h] + nums[i], h))
                    if nums[h] > s:
                        inv += 1
                    sl.add((nums[h] + s, h))
                if pos + 2 < len(idx):
                    k = idx[pos + 2]
                    if nums[j] > nums[k]:
                        inv -= 1
                    sl.remove((nums[j] + nums[k], j))
                    if s > nums[k]:
                        inv += 1
                    sl.add((s + nums[k], i))
    
                nums[i] = s
                idx.remove(j)
            return ans
    
    
  • func minimumPairRemoval(nums []int) (ans int) {
    	type pair struct{ s, i int }
    
    	n := len(nums)
    	inv := 0
    
    	sl := redblacktree.NewWith[pair, struct{}](func(a, b pair) int { return cmp.Or(a.s-b.s, a.i-b.i) })
    	idx := redblacktree.New[int, struct{}]()
    	for i := 0; i < n; i++ {
    		idx.Put(i, struct{}{})
    	}
    
    	for i := 0; i < n-1; i++ {
    		if nums[i] > nums[i+1] {
    			inv++
    		}
    		sl.Put(pair{nums[i] + nums[i+1], i}, struct{}{})
    	}
    
    	for inv > 0 {
    		ans++
    
    		it := sl.Iterator()
    		it.First()
    		p := it.Key()
    		sl.Remove(p)
    
    		s, i := p.s, p.i
    
    		jNode, _ := idx.Ceiling(i + 1)
    		j := jNode.Key
    
    		if nums[i] > nums[j] {
    			inv--
    		}
    
    		if hNode, ok := idx.Floor(i - 1); ok {
    			h := hNode.Key
    
    			if nums[h] > nums[i] {
    				inv--
    			}
    			sl.Remove(pair{nums[h] + nums[i], h})
    
    			if nums[h] > s {
    				inv++
    			}
    			sl.Put(pair{nums[h] + s, h}, struct{}{})
    		}
    
    		if kNode, ok := idx.Ceiling(j + 1); ok {
    			k := kNode.Key
    
    			if nums[j] > nums[k] {
    				inv--
    			}
    			sl.Remove(pair{nums[j] + nums[k], j})
    
    			if s > nums[k] {
    				inv++
    			}
    			sl.Put(pair{s + nums[k], i}, struct{}{})
    		}
    
    		nums[i] = s
    		idx.Remove(j)
    	}
    
    	return
    }
    
    

All Problems

All Solutions