能否用new Set解决数独多维数组去重与空白填充问题?
Set (Preserving Original Positions) Great question! Using Set is a smart approach for tracking used numbers in rows and columns, and you don't have to worry about it messing up element indices—we'll work directly with the original array's positions to only fill in the 0s without touching existing values. Let's walk through how to implement this step by step.
First: Understand the Limitation of Your Current Code
Your current code only grabs unique values from each row, but it includes 0 and doesn't account for column constraints. We need to:
- Exclude
0from our "used numbers" sets (since blanks don't count as filled values) - Check both the row and column for used numbers when determining valid fills for a blank cell
Step-by-Step Implementation
Let's build out the solution:
Create a helper function to get used numbers in a column
We'll loop through each row to collect non-zero values from the target column:function getUsedInColumn(grid, colIndex) { const used = new Set(); for (let row = 0; row < grid.length; row++) { const value = grid[row][colIndex]; if (value !== 0) { used.add(value); } } return used; }Loop through each cell in the grid
For every cell that's0, we'll:- Get all used numbers in its row (excluding
0) - Get all used numbers in its column (excluding
0) - Combine these sets to find which numbers are unavailable
- Pick a valid number (from 1-9 not in the combined set) to fill the blank
- Get all used numbers in its row (excluding
Put it all together
Here's the full code that modifies the original grid only by filling0s:let nums = [ [1, 0, 5, 8, 0, 2, 0, 0, 0], [0, 9, 0, 0, 7, 6, 4, 0, 5], [2, 0, 0, 4, 0, 0, 8, 1, 9], [0, 1, 9, 0, 0, 7, 3, 0, 6], [7, 6, 2, 0, 8, 3, 0, 9, 0], [0, 0, 0, 0, 6, 1, 0, 5, 0], [0, 0, 7, 6, 0, 0, 0, 3, 0], [4, 3, 0, 0, 2, 0, 5, 0, 1], [6, 0, 0, 3, 0, 8, 9, 0, 0] ]; // Helper to get used numbers in a column function getUsedInColumn(grid, colIndex) { const used = new Set(); for (let row = 0; row < grid.length; row++) { const value = grid[row][colIndex]; if (value !== 0) { used.add(value); } } return used; } // Fill in the blanks for (let row = 0; row < nums.length; row++) { const usedInRow = new Set(nums[row].filter(num => num !== 0)); for (let col = 0; col < nums[row].length; col++) { if (nums[row][col] === 0) { const usedInColumn = getUsedInColumn(nums, col); // Combine used numbers from row and column const allUsed = new Set([...usedInRow, ...usedInColumn]); // Find the first valid number (1-9 not in allUsed) for (let num = 1; num <= 9; num++) { if (!allUsed.has(num)) { nums[row][col] = num; // Update the row's used set with the new number usedInRow.add(num); break; } } } } } // Log the result console.log(nums);
Key Notes to Reassure You About Index Positions
- We're directly iterating over the original
numsarray using row and column indices. Non-zero values are never modified—we only target cells wherenums[row][col] === 0. - The
Setis just a tool to track used numbers; it doesn't rearrange or alter the original array's structure or existing element positions at all.
A Quick Caveat
This solution fills blanks with the first valid number found in 1-9 order. Real Sudoku requires considering 3x3 subgrids too, but based on your question's focus on rows and columns, this implementation meets your stated requirements.
内容的提问来源于stack exchange,提问作者Zum Dummi

