LeetCode Algorithm 0036 - 0040

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/darkrabbit/article/details/82927182

LeetCode Algorithm 0036 - 0040



0036 - Valid Sudoku (Medium)

Problem Link: https://leetcode.com/problems/valid-sudoku/description/

Description

Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules :

  • 1. Each row must contain the digits 1-9 without repetition.

  • 2. Each column must contain the digits 1-9 without repetition.

  • 3. Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.

question 36

A partially filled sudoku which is valid.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.

Example 1:

Input:
[
  ["5","3",".",".","7",".",".",".","."],
  ["6",".",".","1","9","5",".",".","."],
  [".","9","8",".",".",".",".","6","."],
  ["8",".",".",".","6",".",".",".","3"],
  ["4",".",".","8",".","3",".",".","1"],
  ["7",".",".",".","2",".",".",".","6"],
  [".","6",".",".",".",".","2","8","."],
  [".",".",".","4","1","9",".",".","5"],
  [".",".",".",".","8",".",".","7","9"]
]
Output: true

Example 2:

Input:
[
  ["8","3",".",".","7",".",".",".","."],
  ["6",".",".","1","9","5",".",".","."],
  [".","9","8",".",".",".",".","6","."],
  ["8",".",".",".","6",".",".",".","3"],
  ["4",".",".","8",".","3",".",".","1"],
  ["7",".",".",".","2",".",".",".","6"],
  [".","6",".",".",".",".","2","8","."],
  [".",".",".","4","1","9",".",".","5"],
  [".",".",".",".","8",".",".","7","9"]
]
Output: false
Explanation: Same as Example 1, except with the 5 in the top left corner being 
    modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.

Note:

  • A Sudoku board (partially filled) could be valid but is not necessarily solvable.

  • Only the filled cells need to be validated according to the mentioned rules.

  • The given board contain only digits 1-9 and the character '.'.

  • The given board size is always 9x9.

Solution C++

#pragma once

#include "pch.h"

// Problem: https://leetcode.com/problems/valid-sudoku/description/

namespace P36ValidSudoku
{
    class Solution
    {
        public:
        bool isValidSudoku(vector<vector<char>>& board)
        {
            if (board.empty())
            {
                return false;
            }

            // 这个解决方案,可以通过LeetCode,但一些数独结果是错误的。
            // 例如:
            //
            // [[".",".",".", ".",".",".", "1",".","."]
            // ,[".",".",".", ".",".",".", ".",".","."]
            // ,[".",".",".", ".",".",".", ".",".","."]
            //
            // ,[".",".",".", ".",".",".", ".","2","."]
            // ,[".",".",".", ".",".",".", ".","3","."]
            // ,[".",".",".", ".",".",".", ".","4","."]
            //
            // ,[".",".",".", ".",".",".", ".",".","."]
            // ,[".",".",".", ".",".",".", ".",".","."]
            // ,[".",".",".", ".",".",".", ".",".","1"]]
            //
            // 本代码是true,LeetCode的官方答案运行结果也是true
            // 但实际上这是一个不合格的数独,结果应该是false

            // row num
            bool usedRows[9][9] = { false };
            // col num
            bool usedCols[9][9] = { false };
            // cube num
            bool usedCubes[9][9] = { false };

            for (int r = 0; r < board.size(); r++)
            {
                for (int c = 0; c < board[r].size(); c++)
                {
                    if (board[r][c] == '.')
                    {
                        continue;
                    }

                    // 检测的数字
                    int checkNum = board[r][c] - '0' - 1;
                    // 第几个九宫格 
                    int cubeIndex = r / 3 * 3 + c / 3;

                    // 数字是否已经存在
                    if (usedRows[r][checkNum] 
                        || usedCols[c][checkNum]
                        || usedCubes[cubeIndex][checkNum])
                    {
                        return false;
                    }

                    usedRows[r][checkNum] = true;
                    usedCols[c][checkNum] = true;
                    usedCubes[cubeIndex][checkNum] = true;
                }
            }

            return true;
        }
    };
}


0037 - Sudoku Solver (Hard)

Problem Link: https://leetcode.com/problems/sudoku-solver/description/

Description

Write a program to solve a Sudoku puzzle by filling the empty cells.

A sudoku solution must satisfy all of the following rules :

  • 1. Each of the digits 1-9 must occur exactly once in each row.

  • 2. Each of the digits 1-9 must occur exactly once in each column.

  • 3. Each of the the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.

Empty cells are indicated by the character '.'.

question 37

A sudoku puzzle…

question 37 solution

…and its solution numbers marked in red.

Note:

  • The given board contain only digits 1-9 and the character '.'.

  • You may assume that the given Sudoku puzzle will have a single unique solution.

  • The given board size is always 9x9.

Solution C++

#pragma once

#include "pch.h"

// Problem: https://leetcode.com/problems/sudoku-solver/description/

namespace P37SudokuSolver
{
    class Solution
    {
        public:
        void solveSudoku(vector<vector<char>>& board)
        {
            if (board.empty() || board.size() != 9 || board[0].size() != 9)
            {
                return;
            }

            // 空白处的行列坐标
            vector<pair<int, int>> noNumIndexes;

            // 数独是否有效
            bool usedRows[9][9] = { false };
            bool usedCols[9][9] = { false };
            bool usedCubes[9][9] = { false };
            if (!isValidSudoku(board, usedRows, usedCols, usedCubes, noNumIndexes))
            {
                return;
            }

            // 计算结果
            solving(board, usedRows, usedCols, usedCubes, noNumIndexes, 0);
        }

        private:
        // 计算数独递归
        bool solving(vector<vector<char>>& board,
                     bool usedRows[9][9],
                     bool usedCols[9][9],
                     bool usedCubes[9][9],
                     vector<pair<int, int>>& noNumIndexes, // 空白处的行列坐标
                     int curNoNumIndex)
        {
            if (curNoNumIndex == noNumIndexes.size())
            {
                return true;
            }

            // 在board中的行列
            pair<int, int> index = noNumIndexes[curNoNumIndex];

            // 第几个九宫格
            int cubeIndex = index.first / 3 * 3 + index.second / 3;

            // 可以填入的数字集合
            unordered_set<int> numSet = unordered_set<int>();
            for (int num = 0; num < 9; num++)
            {
                if (usedRows[index.first][num] 
                    || usedCols[index.second][num]
                    || usedCubes[cubeIndex][num])
                {
                    continue;
                }

                numSet.insert(num);
            }

            // 没有可以填入的数字
            if (numSet.size() == 0)
            {
                return false;
            }
            
            // 开始计算:挨个填入可用数字
            for (int num : numSet)
            {
                usedRows[index.first][num] = true;
                usedCols[index.second][num] = true;
                usedCubes[cubeIndex][num] = true;

                board[index.first][index.second] = (char)(num + 1 + '0');
                if (solving(board, usedRows, usedCols, usedCubes, noNumIndexes, curNoNumIndex + 1))
                {
                    return true;
                }

                // 填入的数字有错误
                usedRows[index.first][num] = false;
                usedCols[index.second][num] = false;
                usedCubes[cubeIndex][num] = false;
            }

            return false;
        }

        // 本函数修改来自36,函数bug参考36注释
        // 检测数独是否有效
        bool isValidSudoku(vector<vector<char>>& board, 
                           bool usedRows[9][9], 
                           bool usedCols[9][9], 
                           bool usedCubes[9][9], 
                           vector<pair<int, int>>& noNumIndexes)
        {
            for (int r = 0; r < board.size(); r++)
            {
                for (int c = 0; c < board[r].size(); c++)
                {
                    if (board[r][c] == '.')
                    {
                        noNumIndexes.push_back(pair<int, int>(r, c));
                        continue;
                    }

                    int checkNum = board[r][c] - '0' - 1;
                    int cubeIndex = r / 3 * 3 + c / 3;
                    if (usedRows[r][checkNum]
                        || usedCols[c][checkNum]
                        || usedCubes[cubeIndex][checkNum])
                    {
                        return false;
                    }

                    usedRows[r][checkNum] = true;
                    usedCols[c][checkNum] = true;
                    usedCubes[cubeIndex][checkNum] = true;
                }
            }

            return true;
        }
    };
}


0038 - Count and Say (Easy)

Problem Link: https://leetcode.com/problems/count-and-say/description/

Description

The count-and-say sequence is the sequence of integers with the first five terms as following:

1.     1
2.     11
3.     21
4.     1211
5.     111221

1 is read off as "one 1" or 11.

11 is read off as "two 1s" or 21.

21 is read off as "one 2, then one 1" or 1211.

Given an integer n where 1 ≤ n ≤ 30, generate the nth term of the count-and-say sequence.

Note: Each term of the sequence of integers will be represented as a string.

Example 1:

Input: 1
Output: "1"

Example 2:

Input: 4
Output: "1211"

Solution C++

#pragma once

#include "pch.h"

// Problem: https://leetcode.com/problems/count-and-say/description/

namespace P38CountAndSay
{
    class Solution
    {
        public:
        string countAndSay(int n)
        {
            // 题目意思就是,每次输出上一次出现数字的个数。
            //  1.     1         1
            //  2.     11        一个1
            //  3.     21        两个1
            //  4.     1211      一个2,一个1
            //  5.     111221    一个1,一个2,2个1

            // 不符合要求的数字
            if (n < 1 || n > 30)
            {
                return "-1";
            }

            if (n == 1)
            {
                return "1";
            }

            string last = countAndSay(n - 1);

            string cur = "";
            for (size_t i = 0; i < last.size(); i++)
            {
                if (cur == "" || last[i] != cur.back())
                {
                    cur += "1";
                    cur += last[i];
                }
                else
                {
                    int index = cur.size() - 2;
                    cur[index] += 1;
                }
            }

            return cur;
        }
    };
}


0039 - Combination Sum (Medium)

Problem Link: https://leetcode.com/problems/combination-sum/description/

Description

Given a set of candidate numbers (candidates) ( without duplicates ) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

The same repeated number may be chosen from candidates unlimited number of times.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
  [7],
  [2,2,3]
]

Example 2:

Input: candidates = [2,3,5], target = 8,
A solution set is:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

Solution C++

#pragma once

#include "pch.h"

// Problem: https://leetcode.com/problems/combination-sum/description/

namespace P39CombinationSum
{
    class Solution
    {
        public:
        vector<vector<int>> combinationSum(vector<int>& candidates, int target)
        {
            vector<vector<int>> results;
            vector<int> result;
            combinationSumInternal(candidates, target, results, result, 0);
            return results;
        }

        private:
        void combinationSumInternal(vector<int>& candidates, 
                                    int target, 
                                    vector<vector<int>>& results, 
                                    vector<int>& result, 
                                    int startIndex)
        {
            for (int i = 0; i < candidates.size(); i++)
            {
                int sub = target - candidates[i];

                if (sub < 0)
                {
                    continue;
                }

                result.push_back(candidates[i]);
                if (sub == 0)
                {
                    results.push_back(result);
                }
                else
                {
                    combinationSumInternal(candidates, sub, results, result, i);
                }
                result.pop_back();
            }
        }
    };
}


0040 - Combination Sum II (Medium)

Problem Link: https://leetcode.com/problems/combination-sum-ii/description/

Description

Given a set of candidate numbers (candidates) ( without duplicates ) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

Each number in candidates may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
  [1,2,2],
  [5]
]

Solution C++

#pragma once

#include "pch.h"

// Problem: https://leetcode.com/problems/combination-sum-ii/description/

namespace P40CombinationSumII
{
    class Solution
    {
        public:
        vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
        {
            vector<vector<int>> results;
            vector<int> result;
            sort(candidates.begin(), candidates.end());
            combinationSumInternal(candidates, target, results, result, 0);
            return results;
        }

        private:
        void combinationSumInternal(vector<int>& candidates, 
                                    int target, 
                                    vector<vector<int>>& results, 
                                    vector<int>& result, 
                                    int startIndex)
        {
            for (int i = startIndex; i < candidates.size(); i++)
            {
                if (i > startIndex && candidates[i] == candidates[i - 1])
                {
                    continue;
                }

                int sub = target - candidates[i];

                if (sub < 0)
                {
                    continue;
                }

                result.push_back(candidates[i]);
                if (sub == 0)
                {
                    results.push_back(result);
                }
                else
                {
                    combinationSumInternal(candidates, sub, results, result, i + 1);
                }
                result.pop_back();
            }
        }
    };
}


猜你喜欢

转载自blog.csdn.net/darkrabbit/article/details/82927182