[程序员面试题精选100题]58.八皇后问题

题目

在8×8的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请求出总共有多少种摆法。

思路

这就是有名的八皇后问题。解决这个问题通常需要用递归,而递归对编程能力的要求比较高。因此有不少面试官青睐这个题目,用来考察应聘者的分析复杂问题的能力以及编程的能力。

由于八个皇后的任意两个不能处在同一行,那么这肯定是每一个皇后占据一行。于是我们可以定义一个数组colIndex[8],colIndex[i]表示位于第i行的皇后的列号。先把colIndex的八个数字分别用0-7初始化,接下来我们要做的事情就是对数组colIndex做全排列。由于我们是用不同的数字初始化数组中的数字,因此任意两个皇后肯定不同列。我们只需要判断得到的每一个排列对应的八个皇后是不是在同一对角斜线上,也就是数组的两个下标i和j,是不是i-j==colIndex[i]-colIndex[j]或者j-i==colIndex[i]-colIndex[j]。

关于全排列问题参考:[LeetCode]46.Permutations

代码

    /*------------------------------------
    *   日期:2015-04-04
    *   作者:SJF0115
    *   题目: 58.八皇后问题
    *   来源:程序员面试题精选100题
    ---------------------------------------*/
    #include <iostream>
    #include <vector>
    using namespace std;

    // 判断皇后是否在同一对角线上
    bool Check(vector<int> colIndex,int n){
        bool a,b;
        for(int i = 0;i < n;++i){
            for(int j = i+1;j < n;++j){
                a = (i - j == colIndex[i] - colIndex[j]);
                b = (j - i == colIndex[i] - colIndex[j]);
                if(a || b){
                    return false;
                }//if
            }//for
        }//for
        return true;
    }

    // 全排列
    void Permutation(vector<int> &colIndex,int n,int index,int &count,vector<bool> &visited){
        if(index == n){
            // 判断皇后是否在同一对角线上
            if(Check(colIndex,n)){
                ++count;
                for(int i = 0;i < n;++i){
                    cout<<colIndex[i]<<" ";
                }//for
                cout<<endl;
            }//if
            return;
        }//if
        for(int i = 0;i < n;++i){
            // 判断是否访问过
            if(!visited[i]){
                colIndex[index] = i;
                visited[i] = true;
                Permutation(colIndex,n,index+1,count,visited);
                visited[i] = false;
            }//if
        }//for
    }

    int EightQueen(){
        int count = 0;
        int n = 8;
        // colIndex[i]表示位于第i行的皇后列号
        vector<int> colIndex(n,0);
        vector<bool> visited(n,false);
        Permutation(colIndex,n,0,count,visited);
        return count;
    }

    int main(){
        //freopen("C:\\Users\\Administrator\\Desktop\\c++.txt", "r", stdin);
        cout<<EightQueen()<<endl;
        return 0;
    }
时间: 2024-09-22 09:51:22

[程序员面试题精选100题]58.八皇后问题的相关文章

[程序员面试题精选100题]9.链表中倒数第k个结点

题目 输入一个单向链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针. 思路一 因为是单向链表,只有从前往后的指针而没有从后往前的指针.因此我们不能倒序遍历链表,只能正序遍历.假设整个链表有n个结点,那么倒数第k个结点是从头结点开始的第n-k-1个结点(从0开始计数).我们只需要得到链表中结点的个数n,那我们只要从头结点开始往后走n-k-1步就可以了. 因此这种方法需要遍历链表两次.第一次得到链表中结点个数n,第二次得到从头结点开始的第n-k-1个结点即倒数第k个结点.时间复杂

[程序员面试题精选100题]1.把二叉查找树转变成排序的双向链表

[题目] 输入一棵二叉查找树,将该二叉查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 比如将二叉查找树                                            10                                          /    \                                        6       14                                      / 

[程序员面试题精选100题]50.树的子结构

题目 输入两棵二叉树A和B,判断树B是不是A的子结构. 例如,下图中的两棵树A和B,由于A中有一部分子树的结构和B是一样的,因此B就是A的子结构. 思路 这是2010年微软校园招聘时的一道题目.二叉树一直是微软面试题中经常出现的数据结构.对微软有兴趣的读者一定要重点关注二叉树. 回到这个题目的本身.要查找树A中是否存在和树B结构一样的子树,我们可以分为两步: (1)树A中找到和B的根结点的值一样的结点N (2)再判断树A中以N为根结点的子树是不是包括和树B一样的结构. 第一步在树A中查找与根结点

[程序员面试题精选100题]6.二叉查找树的后序遍历结果

[题目] 输入一个整数数组,判断该数组是不是某二叉查找树的后序遍历的结果.如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果:           8         /    \       6    10      /   \   /   \    5    7 9 11 因此返回true. 如果输入7.4.6.5,没有哪棵树的后序遍历的结果是这个序列,因此返回false. [分析] 这是一道trilogy的笔试题,主要考

[程序员面试题精选100题]12.从上往下遍历二叉树

[题目] 输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印. 例如输入         8      /      \     6     10    /   \     /  \   5  7   9  11 输出8   6   10   5   7   9   11 [分析] 这曾是微软的一道面试题.这道题实质上是要求遍历一棵二元树,只不过不是我们熟悉的前序.中序或者后序遍历. 我们从树的根结点开始分析.自然先应该打印根结点8,同时为了下次能够打印8的两个子结点,

[程序员面试题精选100题]13.第一个只出现一次的字符

[题目] 在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b. [分析] [代码] /********************************* * 日期:2013-12-23 * 作者:SJF0115 * 题目: 13.第一个只出现一次的字符 * 来源:微软 * 分类:程序员面试题精选100题 **********************************/ #include <iostream> #include <cstring> us

[程序员面试题精选100 题]17.把字符串转换成整数

题目 输入一个表示整数的字符串,把该字符串转换成整数并输出.例如输入字符串"345",则输出整数345. 分析 这道题尽管不是很难,学过 C/C++语言一般都能实现基本功能,但不同程序员就这道题写出的代码有很大区别,可以说这道题能够很好地反应出程序员的思维和编程习惯,因此已经被包括微软在内的多家公司用作面试题.建议读者在往下看之前自己先编写代码,再比较自己写的代码和下面的参考代码有哪些不同. 我们需要考虑一下几个方面的问题: (1)正负问题: 由于整数可能不仅仅之含有数字,还有可能以'

[程序员面试题精选100题]19.反转链表

题目 输入一个链表的头结点,反转该链表,并返回反转后链表的头结点. 分析 假设经过若干操作,我们已经把结点 pre之前的指针调整完毕,这些结点的next指针都指向前面一个结点.现在我们遍历到结点cur.我们需要把调整结点的next指针让它指向前一个结点pre.注意一旦调整了指针的指向,链表就断开了,如下图所示: 因为已经没有指针指向结点nextNode,我们没有办法再遍历到结点nextNode 了.因此为了避免链表断开,我们需要在调整cur的next指针之前要把nextNode保存下来. 代码

[程序员面试题精选100题]10.排序数组中和为给定值的两个数字

剑指Offer之和为S的两个数字 剑指Offer之和为S的连续正数序列 扩展(1):输入一个数组,判断这个数组中是不是存在三个数字i, j, k,满足i+j+k等于0. 扩展(2):如果输入的数组是没有排序的,但知道里面数字的范围,其他条件不变,如何在O(n)时间里找到这两个数字?这个的基本思路是先用哈希表实现O(n)的排序(请参照本面试题系列的第57题),接下来的步骤都一样了.