N-Queens II -- leetcode

Follow up for N-Queens problem.

Now, instead outputting board configurations, return the total number of distinct solutions.

算法一

利用permutation中使用swap的思路,可以快速满足列条件的限制。

这样,在检查合法性时,只需要检查是否满足对角线的限制即可。

此算法在leetcode上的实际的执行时间为4ms。

class Solution {
public:
    int totalNQueens(int n) {
        int sum = 0;
        vector<int> solution;
        for (int i=0; i<n; i++)
                solution.push_back(i);

        helper(solution, 0, sum);
        return sum;
    }

    void helper(vector<int> &solution, int start, int &sum) {
        if (start == solution.size()) {
                ++sum;
                return;
        }

        for (int i=start; i<solution.size(); i++) {
                swap(solution[i], solution[start]);
                if (isValid(solution, start)) {
                        helper(solution, start+1, sum);
                }
                swap(solution[i], solution[start]);
        }
    }

    bool isValid(vector<int> &solution, int start) {
        for (int i=start-1; i>=0; --i) {
                if (start-i == abs(solution[start]-solution[i]))
                        return false;
        }
        return true;
    }
};

算法二:

基于回溯法。

特点,利用3个数组,分别记录剩下的列,以及由左对角线,右对角线的限制。

这样在回溯时,可以快速确定某个位置,是否可用。

此算法在leetcode上实际执行时间为3ms。

注,这里选择vector<char>,而不是vector<bool>。这是基于性能考虑,如果选择vector<bool>,执行时间会达到8ms。

原因,则是因为stl 对vector<bool>作了比特化的特化,虽说是省了空间,但却是以时间为代价。

class Solution {
public:
    int totalNQueens(int n) {
        int sum = 0;
        vector<int> cl; //  column
        vector<char> ld(n*2);  //left diagonal
        vector<char> rd(n*2); // right diagonal

        for (int i=0; i<n; i++)
                cl.push_back(i);

        helper(cl, 0, ld, 0, rd, n, sum);
        return sum;
    }

    void helper(vector<int> &cl, int start_cl, vector<char> &ld, int start_ld, vector<char> &rd, int start_rd, int &sum) {
        if (start_cl == cl.size()) {
                ++sum;
                return;
        }

        for (int i=start_cl; i<cl.size(); i++) {
                const int ldi = start_ld + cl[i];
                const int rdi = start_rd + cl[i];

                if (!ld[ldi] && !rd[rdi]) {
                        ld[ldi] = rd[rdi] = true;
                        swap(cl[i], cl[start_cl]);
                        helper(cl, start_cl+1, ld, start_ld+1, rd, start_rd-1, sum);
                        swap(cl[i], cl[start_cl]);
                        ld[ldi] = rd[rdi] = false;
                }
        }
    }
};

算法二,与算法一的主要差别是:

算法二用

!ld[ldi] && !rd[rdi]

这一句代替了算法一中isValid() 函数。

时间: 2024-11-01 16:09:25

N-Queens II -- leetcode的相关文章

Pascal&#39;s Triangle II Leetcode java

题目: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3,3,1]. Note: Could you optimize your algorithm to use only O(k) extra space? 题解: 为了达到O(k)的空间复杂度要求,那么就要从右向左生成结果.相当于你提前把上一行的计算出来,当前行就可以用上一次计算出的结果计算了

Spiral Matrix II leetcode java

题目: Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For example, Given n = 3, You should return the following matrix: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] 题解:这道题跟Spiral Matrix想法也是类似的,就是依照矩阵从外圈到内圈建立

Permutations II leetcode java

题目: Given a collection of numbers that might contain duplicates, return all possible unique permutations. For example, [1,1,2] have the following unique permutations: [1,1,2], [1,2,1], and [2,1,1]. 题解: 这道题跟Permutaitons没啥大的区别,就是结果去重. 我之前也有写过去重的两个方法: 一

Combination Sum II leetcode java

题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. Each number in C may only be used once in the combination. Note: All numbers (including target) will be

Reverse Linked List II leetcode java

题目: Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->5->NULL. Note: Given m, n satisfy the following condition: 1 ≤ m ≤ n

Word Ladder II leetcode java

题目: Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that: Only one letter can be changed at a time Each intermediate word must exist in the dictionary For example, Given: start =

Populating Next Right Pointers in Each Node II leetcode java

题目: Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tree could be any binary tree? Would your previous solution still work? Note: You may only use constant extra space. For example, Given the following bina

Unique Binary Search Trees II leetcode java

题目: Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For example, Given n = 3, your program should return all 5 unique BST's shown below. 1 3 3 2 1 \ / / / \ 3 2 1 1 3 2 / / \ 2 1 2 3 题解:这道题比1难的就是不是返回个数,而

Path Sum II leetcode java

题目: Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. For example: Given the below binary tree and sum = 22, 5 / 4 8 / / 11 13 4 / \ / 7 2 5 1 return [ [5,4,11,2], [5,8,4,5] ] 题解: 这道题除了要判断是否有这样的一个p

Pascal&#39;s triangle II Leetcode Python

Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3,3,1]. Note: Could you optimize your algorithm to use only O(k) extra space? 这题和前面一题的区别在于不用返回所有解,只需要返回index对应行就行.做法和前面的一样定义一个currow 和prerow class Solu