双数组过滤与修改:贪心算法实现方案技术问询
Hey there! Let's break down how to solve this problem properly—your initial approach with forEach ran into issues because those methods aren't great for modifying arrays while traversing them, and they don't let you easily break out of loops once you find a match. Let's walk through the optimal implementation step by step.
The Problem Recap
You have two arrays:
arr1holds values representing how many elements you want to take from subarrays inarr2arr2is an array of subarrays, and you need to "shift" (or remove from the start) the requested number of elements from the first possible subarray that can accommodate the request- The loop stops when either
arr1is empty, or all subarrays inarr2are empty
Why forEach Didn't Work
forEach iterates over the original array's length, so modifying the array mid-traversal (like removing elements) causes index mismatches. Plus, you can't break out of a forEach loop early—once it starts, it goes through every element, which isn't what we want for this greedy logic.
Optimal Implementation
We'll use a while loop for the outer control (to keep running until our termination conditions are met), paired with nested for loops to find the first valid pair of elements from arr1 and subarrays from arr2. Here's the code:
let arr1 = [3, 3, 2, 2, 1, 1]; let arr2 = [[1, 1, 1, 1], [1, 1, 1], [1, 1], [1]]; // Run until arr1 is empty OR all subarrays in arr2 are empty while (arr1.length > 0 && arr2.some(sub => sub.length > 0)) { let processed = false; // Iterate through arr1 to find the first value we can process for (let i = 0; i < arr1.length; i++) { const takeCount = arr1[i]; // Iterate through arr2 to find the first subarray that can give us takeCount elements for (let j = 0; j < arr2.length; j++) { const subArr = arr2[j]; if (subArr.length >= takeCount) { // Remove the first `takeCount` elements from the subarray (more efficient than multiple shifts) subArr.splice(0, takeCount); // Remove the processed value from arr1 arr1.splice(i, 1); processed = true; break; // Exit arr2 loop once we find a valid subarray } } if (processed) break; // Exit arr1 loop once we process a value, restart the while loop } // If we couldn't process any value in this iteration, we can't make more progress—exit if (!processed) break; } console.log("Final arr1:", arr1); // [2] console.log("Final arr2:", arr2); // [[], [], [], []]
How This Works
- Outer
whileLoop: Checks if we still have elements to process inarr1and if there's at least one non-empty subarray inarr2. - Inner
forLoops:- First, we loop through
arr1to find the first value we can fulfill. - For that value, we loop through
arr2to find the first subarray with enough elements.
- First, we loop through
- Processing:
- Use
splice(0, takeCount)to remove the requested number of elements from the subarray in one go (this is way more efficient than callingshift()takeCounttimes). - Remove the processed value from
arr1withsplice(i, 1). - Set
processedtotrueand break out of both inner loops to restart the process with the updated arrays.
- Use
- Termination Check: If we go through the entire
arr1without processing any elements, it means none of the remaining values can be fulfilled byarr2, so we exit the loop early.
Matching Your Example Steps
This code aligns with your outlined logic:
- Step 1: Takes 3 elements from
arr2[0], updating arrays toarr1 = [3,2,2,1,1],arr2 = [[1], [1,1,1], [1,1], [1]] - Step 2: Takes 3 elements from
arr2[1], updating arrays toarr1 = [2,2,1,1],arr2 = [[1], [], [1,1], [1]] - Step 3: Takes 2 elements from
arr2[2], updating arrays toarr1 = [2,1,1],arr2 = [[1], [], [], [1]] - Step 4: Takes 1 element from the first valid subarray (
arr2[0]in this case—if you need to prioritize later subarrays, just reverse thearr2loop direction) - Step 5: Continues processing until
arr2is fully empty, leavingarr1 = [2]
内容的提问来源于stack exchange,提问作者LirysJH

