【LeetCode从零单刷】N-Queens II

题目:

Follow up for N-Queens problem.

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

解答:

思路很简单,就是暴力求解的N皇后问题计数。过程如下:

  1. 如果第 i 行的第 j 列放着皇后,然后放第 (i+1) 行的皇后使其不矛盾,然后第 (i+2) 行……;
  2. 如果每一列都不可行,那我们就回溯一行,然后继续第 1 步直至成功(转3)或者失败。失败了再次回溯一行然后转第 1 步;
  3. 成功在第 N 行上也放好了皇后,算一种解法。解法总数 +1,回溯到上一行,列数 +1,再次转到第 1 步。

思路也不难。就是代码的实现比较复杂。尤其是回溯的过程。但是如果利用递归的思想,就很简单了。如果在第 i 行的第 j 列放着皇后时的解法数目,表示为 S(i, j)。

解法总数 = S(0, 0) + S(0, 1) + ... + S(0, n)

= [S(1, 0, 此时 (0, 0) 处有一皇后) + S(1, 1, 此时 (0, 0) 处有一皇后) + ...] + [S(1, 0, 此时 (0, 1) 处有一皇后) + S(1, 1, 此时 (0, 1) 处有一皇后) + ...] + ...

= ......

等于就是画出了一棵庞大的树,统计每个子叶节点的解法个数汇集到父节点,父节点再汇集到父节点的父节点......这样一来根节点就是总的解法个数,而中途死掉的节点,计数时就不会计入。

此时如果利用二维数组来计数,执行起来会非常麻烦。这里介绍一个小技巧,仅仅利用一个一维数组,数组第 i 个元素 j 代表在棋盘第 i 行的第 j 列放置一个皇后(或者棋盘第 j 行的第 i 列,这个无所谓)。

同样,我们需要一个check函数判断当前放置一个皇后会不会与之前放置皇后产生矛盾。行、列的判断很简单,对角线的判断稍微复杂点,需要利用到一个性质:

对于坐标为 (a, b) 和 (c, d) 的两个点,如果在对角线相交会有 abs(a-c) == abs(b-d) 的性质。

最终代码:

class Solution {
public:
	// 判断是否与之前已经填入的皇后产生冲突
	bool check(int* queen, int count)
	{
		for (int i = 0; i < count; ++i)
		{
			if (queen[i] == queen[count] || abs(count - i) == abs(queen[count] - queen[i]))
			{
				return false;
			}
		}
		return true;
	}

	// 递归函数
	int iterQueens(int* queen, int count, int row)
	{
		// row 最大有效值是 (n-1),如果 == n 说明已经填完棋盘
		if (count == row)	return 1;

		int sum = 0;
		for (int col = 0; col < count; ++col)
		{
			queen[row] = col;
			if (check(queen, row))
			{
				sum = sum + iterQueens(queen, count, row + 1);
			}
		}
		return sum;
	}

	int totalNQueens(int n) {
		int* queen = new int[n];
		// initiate
		for (int i = 0; i < n; ++i)
		{
			queen[i] = -1;
		}

		return iterQueens(queen, n, 0);
	}
};

对于非递归版本,比这个就麻烦多了。可以查看传送门(应该是正确的解法,但是我写了一遍却是超时不知道为什么……)

最重要的,以上连接中介绍了一种位运算的方法(反正我没看懂,毕竟菜鸡),是最快的求解方法。

时间: 2024-10-08 06:17:50

【LeetCode从零单刷】N-Queens II的相关文章

【LeetCode从零单刷】Binary Tree Inorder Traversal

题目: Given a binary tree, return the inorder traversal of its nodes' values. For example: Given binary tree {1,#,2,3}, 1 2 / 3 return [1,3,2].  Note: Recursive solution is trivial, could you do it iteratively? 解答: 其实思路有点类似以前的一篇文章:[LeetCode从零单刷]Binary

【LeetCode从零单刷】Best Time to Buy and Sell Stock II

题目: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times)

【LeetCode从零单刷】Single Number II

题目: Given an array of integers, every element appears three times except for one. Find that single one. 解答: 如果是挑出非偶数次数的元素,可以利用每个元素依次异或的方法.但是非奇数次数(3,5,7,9--)的元素? 如果要快,可以hash_map存储.然后遍历一遍hash_map找到Single Number. 换种思路,按位找不同的Single Number对应的位.细节上: bit =

【LeetCode从零单刷】Maximum Depth of Binary Tree

没错我就是伍声2009的粉丝,从今天起,模仿<从零单排>系列,菜鸡单刷LeetCode! 题目: Given a binary tree, find its maximum depth.  The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 解答: 树的深度优先遍历,求得树高度即可.然后需要用到递归的思想,假设子树的高

【LeetCode从零单刷】Same Tree

没错我就是伍声2009的粉丝,从今天起,模仿<从零单排>系列,菜鸡单刷LeetCode! 题目: Given two binary trees, write a function to check if they are equal or not.  Two binary trees are considered equal if they are structurally identical and the nodes have the same value. 解答: 验证两棵树是否相等.使

【LeetCode从零单刷】Longest Increasing Subsequence

题目: Given an unsorted array of integers, find the length of longest increasing subsequence. For example, Given [10, 9, 2, 5, 3, 7, 101, 18], The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more

【LeetCode从零单刷】Integer to Roman

题目: Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999. 解答: 慢慢模拟也可以.应该不会错.这里介绍一种"查表+ 拼接字符串"的方法. class Solution { public: string thousand[4] = {"", "M", "MM", &

【LeetCode从零单刷】Excel Sheet Column Number

题目: Given a column title as appear in an Excel sheet, return its corresponding column number. For example: A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 解答: 怎么说,类似26进制数一样.乍看之下挺简单.于是写下: class Solution { public: int titleToNumber(stri

【LeetCode从零单刷】Bulb Switcher

题目: There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it's off or turning off if it's on). For the nth round, you only toggl