Welcome to Subscribe On Youtube

3117. Minimum Sum of Values by Dividing Array

Description

You are given two arrays nums and andValues of length n and m respectively.

The value of an array is equal to the last element of that array.

You have to divide nums into m disjoint contiguous subarrays such that for the ith subarray [li, ri], the bitwise AND of the subarray elements is equal to andValues[i], in other words, nums[li] & nums[li + 1] & ... & nums[ri] == andValues[i] for all 1 <= i <= m, where & represents the bitwise AND operator.

Return the minimum possible sum of the values of the m subarrays nums is divided into. If it is not possible to divide nums into m subarrays satisfying these conditions, return -1.

 

Example 1:

Input: nums = [1,4,3,3,2], andValues = [0,3,3,2]

Output: 12

Explanation:

The only possible way to divide nums is:

  1. [1,4] as 1 & 4 == 0.
  2. [3] as the bitwise AND of a single element subarray is that element itself.
  3. [3] as the bitwise AND of a single element subarray is that element itself.
  4. [2] as the bitwise AND of a single element subarray is that element itself.

The sum of the values for these subarrays is 4 + 3 + 3 + 2 = 12.

Example 2:

Input: nums = [2,3,5,7,7,7,5], andValues = [0,7,5]

Output: 17

Explanation:

There are three ways to divide nums:

  1. [[2,3,5],[7,7,7],[5]] with the sum of the values 5 + 7 + 5 == 17.
  2. [[2,3,5,7],[7,7],[5]] with the sum of the values 7 + 7 + 5 == 19.
  3. [[2,3,5,7,7],[7],[5]] with the sum of the values 7 + 7 + 5 == 19.

The minimum possible sum of the values is 17.

Example 3:

Input: nums = [1,2,3,4], andValues = [2]

Output: -1

Explanation:

The bitwise AND of the entire array nums is 0. As there is no possible way to divide nums into a single subarray to have the bitwise AND of elements 2, return -1.

 

Constraints:

  • 1 <= n == nums.length <= 104
  • 1 <= m == andValues.length <= min(n, 10)
  • 1 <= nums[i] < 105
  • 0 <= andValues[j] < 105

Solutions

We design a function $dfs(i, j, a)$, which represents the possible minimum sum of subarray values that can be obtained starting from the $i$-th element, with $j$ subarrays already divided, and the bitwise AND result of the current subarray to be divided is $a$. The answer is $dfs(0, 0, -1)$.

The execution process of the function $dfs(i, j, a)$ is as follows:

  • If $n - i < m - j$, it means that the remaining elements are not enough to divide into $m - j$ subarrays, return $+\infty$.
  • If $j = m$, it means that $m$ subarrays have been divided. At this time, check whether $i = n$ holds. If it holds, return $0$, otherwise return $+\infty$.
  • Otherwise, we perform a bitwise AND operation on $a$ and $nums[i]$ to get a new $a$. If $a < andValues[j]$, it means that the bitwise AND result of the current subarray to be divided does not meet the requirements, return $+\infty$. Otherwise, we have two choices:
    • Do not divide the current element, i.e., $dfs(i + 1, j, a)$.
    • Divide the current element, i.e., $dfs(i + 1, j + 1, -1) + nums[i]$.
  • Return the minimum of the above two choices.

To avoid repeated calculations, we use the method of memoization search and store the result of $dfs(i, j, a)$ in a hash table.

The time complexity is $O(n \times m \times \log M)$, and the space complexity is $O(n \times m \times \log M)$. Where $n$ and $m$ are the lengths of the arrays $nums$ and $andValues$ respectively; and $M$ is the maximum value in the array $nums$, in this problem $M \leq 10^5$.

  • class Solution {
        private int[] nums;
        private int[] andValues;
        private final int inf = 1 << 29;
        private Map<Long, Integer> f = new HashMap<>();
    
        public int minimumValueSum(int[] nums, int[] andValues) {
            this.nums = nums;
            this.andValues = andValues;
            int ans = dfs(0, 0, -1);
            return ans >= inf ? -1 : ans;
        }
    
        private int dfs(int i, int j, int a) {
            if (nums.length - i < andValues.length - j) {
                return inf;
            }
            if (j == andValues.length) {
                return i == nums.length ? 0 : inf;
            }
            a &= nums[i];
            if (a < andValues[j]) {
                return inf;
            }
            long key = (long) i << 36 | (long) j << 32 | a;
            if (f.containsKey(key)) {
                return f.get(key);
            }
    
            int ans = dfs(i + 1, j, a);
            if (a == andValues[j]) {
                ans = Math.min(ans, dfs(i + 1, j + 1, -1) + nums[i]);
            }
            f.put(key, ans);
            return ans;
        }
    }
    
  • class Solution {
    public:
        int minimumValueSum(vector<int>& nums, vector<int>& andValues) {
            this->nums = nums;
            this->andValues = andValues;
            n = nums.size();
            m = andValues.size();
            int ans = dfs(0, 0, -1);
            return ans >= inf ? -1 : ans;
        }
    
    private:
        vector<int> nums;
        vector<int> andValues;
        int n;
        int m;
        const int inf = 1 << 29;
        unordered_map<long long, int> f;
    
        int dfs(int i, int j, int a) {
            if (n - i < m - j) {
                return inf;
            }
            if (j == m) {
                return i == n ? 0 : inf;
            }
            a &= nums[i];
            if (a < andValues[j]) {
                return inf;
            }
            long long key = (long long) i << 36 | (long long) j << 32 | a;
            if (f.contains(key)) {
                return f[key];
            }
            int ans = dfs(i + 1, j, a);
            if (a == andValues[j]) {
                ans = min(ans, dfs(i + 1, j + 1, -1) + nums[i]);
            }
            return f[key] = ans;
        }
    };
    
  • class Solution:
        def minimumValueSum(self, nums: List[int], andValues: List[int]) -> int:
            @cache
            def dfs(i: int, j: int, a: int) -> int:
                if n - i < m - j:
                    return inf
                if j == m:
                    return 0 if i == n else inf
                a &= nums[i]
                if a < andValues[j]:
                    return inf
                ans = dfs(i + 1, j, a)
                if a == andValues[j]:
                    ans = min(ans, dfs(i + 1, j + 1, -1) + nums[i])
                return ans
    
            n, m = len(nums), len(andValues)
            ans = dfs(0, 0, -1)
            return ans if ans < inf else -1
    
    
  • func minimumValueSum(nums []int, andValues []int) int {
    	n, m := len(nums), len(andValues)
    	f := map[int]int{}
    	const inf int = 1 << 29
    	var dfs func(i, j, a int) int
    	dfs = func(i, j, a int) int {
    		if n-i < m-j {
    			return inf
    		}
    		if j == m {
    			if i == n {
    				return 0
    			}
    			return inf
    		}
    		a &= nums[i]
    		if a < andValues[j] {
    			return inf
    		}
    		key := i<<36 | j<<32 | a
    		if v, ok := f[key]; ok {
    			return v
    		}
    		ans := dfs(i+1, j, a)
    		if a == andValues[j] {
    			ans = min(ans, dfs(i+1, j+1, -1)+nums[i])
    		}
    		f[key] = ans
    		return ans
    	}
    	if ans := dfs(0, 0, -1); ans < inf {
    		return ans
    	}
    	return -1
    }
    
  • function minimumValueSum(nums: number[], andValues: number[]): number {
        const [n, m] = [nums.length, andValues.length];
        const f: Map<bigint, number> = new Map();
        const dfs = (i: number, j: number, a: number): number => {
            if (n - i < m - j) {
                return Infinity;
            }
            if (j === m) {
                return i === n ? 0 : Infinity;
            }
            a &= nums[i];
            if (a < andValues[j]) {
                return Infinity;
            }
            const key = (BigInt(i) << 36n) | (BigInt(j) << 32n) | BigInt(a);
            if (f.has(key)) {
                return f.get(key)!;
            }
            let ans = dfs(i + 1, j, a);
            if (a === andValues[j]) {
                ans = Math.min(ans, dfs(i + 1, j + 1, -1) + nums[i]);
            }
            f.set(key, ans);
            return ans;
        };
        const ans = dfs(0, 0, -1);
        return ans >= Infinity ? -1 : ans;
    }
    
    

All Problems

All Solutions