移除数组相邻重复项:递归方案问题排查与解法探讨
Hey there! Let's figure out why your initial recursive function was logging the correct result but returning undefined, plus walk through other solid ways to solve this problem.
What Went Wrong with Your Initial Recursive Code
The core issue is missing return statements in your recursive branches. When you call remAdjDups() inside the if/else blocks, you don't pass the returned value back up the call stack. So even though the final recursive call correctly returns the output array, none of the parent calls pass that value along—resulting in undefined being returned to the top level.
A secondary (but less critical) issue is using splice() to modify the input array in place, which can make debugging trickier, but that's not the root cause of the return value bug.
Here's the fixed version of your initial code, with the missing return statements added:
const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1]; const remAdjDups = (arr, output = []) => { if (!arr.length) { console.log("Result before return: ", output); return output; } if (arr[0] === arr[1]) { arr.splice(1, 1); // Return the result of the recursive call return remAdjDups(arr, output); } else { // Same here—pass the recursive result up return remAdjDups(arr.slice(1), output.concat(arr[0])); } } let out = remAdjDups(input.slice()); console.log("output: ", out); // Now logs [2, 0, 2, 3, 0, 1]
Your Updated Recursive Solution (Great for Practice!)
Your revised recursive approach is a clean improvement—it uses array destructuring to avoid modifying the original array, and every branch explicitly returns the result of the recursive call. This makes the logic easier to follow and eliminates the return value bug. Let's recap it here for clarity:
const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1, 1, 1, 1]; const remAdjDups = ([x, y, ...rest], out = []) => { if (!rest.length) return (x === y) ? [...out, x] : [...out, x, y]; else if (x === y) return remAdjDups([x, ...rest], out); else return remAdjDups([y, ...rest], [...out, x]); } let out = remAdjDups(input.slice()); console.log("output: ", out); // [2, 0, 2, 3, 0, 1]
Alternative Solutions
If you're looking for other ways to solve this problem, here are two popular approaches:
1. Two-Pointer Iterative Approach (Most Efficient)
This method runs in O(n) time with O(1) extra space (if you're okay modifying the input array; otherwise, use a new array). It uses two pointers to track the end of the result list and iterate through the input:
const removeAdjacentDuplicates = (arr) => { if (arr.length <= 1) return [...arr]; let slow = 0; for (let fast = 1; fast < arr.length; fast++) { // If current element is different from the last unique element if (arr[fast] !== arr[slow]) { slow++; arr[slow] = arr[fast]; } } // Return only the unique elements up to the slow pointer return arr.slice(0, slow + 1); }; const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1]; console.log(removeAdjacentDuplicates(input)); // [2, 0, 2, 3, 0, 1]
2. Array.reduce() (Concise & Readable)
For a more declarative approach, use reduce() to build your result array by checking each element against the last element in the accumulator:
const removeAdjacentDuplicates = (arr) => { return arr.reduce((acc, curr) => { // Only add the current element if it's not the same as the last one in the accumulator if (acc[acc.length - 1] !== curr) { acc.push(curr); } return acc; }, []); }; const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1]; console.log(removeAdjacentDuplicates(input)); // [2, 0, 2, 3, 0, 1]
内容的提问来源于stack exchange,提问作者Shidersz

