LeetCode051 N-Queens

本文提供了一种解决N皇后问题的有效方法,通过回溯算法在Java、C和Python中实现,实现了在N×N的棋盘上放置N个皇后,使得任意两个皇后都不会互相攻击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

详细见:leetcode.com/problems/n-queens


Java Solution: github

package leetcode;

import java.util.LinkedList;
import java.util.List;

public class P051_NQueens {
	public static void main(String[] args) {
//		Queen queen = new Queen();
//		queen.backtrack(1);
		System.out.println(new Solution2().solveNQueens(8).size());
	}
	/*
	 * 	4 ms
	 * 	91.55% 
	 */
	static class Solution1 {
		List<List<String>> ans = new LinkedList<List<String>>();
		int[] col = null, rup = null, lup = null, row = null;
		public List<List<String>> solveNQueens(int n) {
			if (n < 1)
				return ans;
			col = new int[n];
			row = new int[n];
			rup = new int[(n << 1) - 1];
			lup = new int[rup.length];
			search(0);
			return ans;
		}
		private void search(int index) {
			if (index == col.length) {
				List<String> answer = new LinkedList<String>();
				char[] cs = new char[index];
				for (int i = 0; i != index; i ++) {
					for (int j = 0; j != index; j ++)
						cs[j] = j == row[i] ? 'Q' : '.';
					answer.add(new String(cs));
				}
				ans.add(answer);
				return;
			}
			for (int i = 0; i != col.length; i ++) {
				if (col[i] == 0 && lup[index + i] == 0 && rup[col.length - 1 + index - i] == 0) {
					col[i] = lup[index + i] = rup[col.length - 1 + index - i] = 1;
					row[index] = i;
					search(index + 1);
					col[i] = lup[index + i] = rup[col.length - 1 + index - i] = 0;
				}
			}
		}
	}
	/*
	 * 	3 ms
	 * 	97.29%
	 */
	static class Solution2 {
		List<List<String>> ans = new LinkedList<List<String>>();
		boolean[] col = null, rup = null, lup = null;
		int[] row = null;
		public List<List<String>> solveNQueens(int n) {
			if (n < 1)
				return ans;
			col = new boolean[n];
			row = new int[n];
			rup = new boolean[(n << 1) - 1];
			lup = new boolean[rup.length];
			search(0);
			return ans;
		}
		private void search(int index) {
			if (index == col.length) {
				List<String> answer = new LinkedList<String>();
				char[] cs = new char[index];
				for (int i = 0; i != index; i ++) {
					for (int j = 0; j != index; j ++)
						cs[j] = j == row[i] ? 'Q' : '.';
					answer.add(new String(cs));
				}
				ans.add(answer);
				return;
			}
			for (int i = 0; i != col.length; i ++) {
				if (! col[i] && ! lup[index + i] && ! rup[col.length - 1 + index - i]) {
					col[i] = lup[index + i] = rup[col.length - 1 + index - i] = true;
					row[index] = i;
					search(index + 1);
					col[i] = lup[index + i] = rup[col.length - 1 + index - i] = false;
				}
			}
		}
	}
}


C Solution: github

/*
    url: leetcode.com/problems/n-queens/
    AC 6ms 16.67%
    AC 3ms 50.00%
*/

#include <stdio.h>
#include <stdlib.h>

//array list start

typedef char** T;
typedef struct al sal;
typedef struct al * pal;

struct al {
    int capacity;
    int size;
    T* arr;
};

void al_expand_capacity(pal l) {
    T* new_arr = (T*) malloc(sizeof(T) * (l->capacity * 2 + 1));
    int i = 0;
    for (i = 0; i < l->capacity; i ++)
        new_arr[i] = l->arr[i];
    free(l->arr);
    l->arr = new_arr;
    l->capacity = l->capacity * 2 + 1;
}

void al_add_last(pal l, T v) {
    if (l->capacity == l->size) al_expand_capacity(l);
    l->arr[l->size] = v;
    l->size ++;
}

void al_add_to_index(pal l, T v, int index) {
    int i = 0;
    if (index > l->size) return;
    if (l->capacity == l->size) al_expand_capacity(l);
    for (i = l->size - 1; i >= index; i --) {
        l->arr[i+1] = l->arr[i];
    }
    l->arr[index] = v;
    l->size ++;
}

T* al_convert_to_array_free_l(pal l) {
    T* arr = l->arr;
    free(l);
    return arr;
}

T al_access_by_index(pal l, int index) {
    if (index >= l->size || index < 0) return 0;
    return l->arr[index];
}

//array list end


int valid(char** save, int i, int j, int n) {
    int k = 0, ii = 0, jj = 0;
    for (k = 0; k < n; k ++) {
        if (k != i && save[k][j] == 'Q') return 0;
        if (k != j && save[i][k] == 'Q') return 0;
    }
    ii = i + 1;
    jj = j + 1;
    while (ii < n && jj < n) {
        if (save[ii][jj] != 'Q') {
            ii ++;
            jj ++;
        } else return 0;
    }
    ii = i - 1;
    jj = j - 1;
    while (ii > -1 && jj > -1) {
        if (save[ii][jj] != 'Q') {
            ii --;
            jj --;
        } else return 0;
    }
    ii = i + 1;
    jj = j - 1;
    while (ii < n && jj > -1) {
        if (save[ii][jj] != 'Q') {
            ii ++;
            jj --;
        } else return 0;
    }
    ii = i - 1;
    jj = j + 1;
    while (ii > -1 && jj < n) {
        if (save[ii][jj] != 'Q') {
            ii --;
            jj ++;
        } else return 0;
    }
    return 1;
}

void solve(pal l, char** save, int row, int n) {
    char** temp = NULL, *temp_row = NULL;
    int i = 0, j = 0, col = 0;
    if (row == n) {
        temp = (char**) malloc(sizeof(char*) * n);;
        for (i = 0; i < n; i ++) {
            temp_row = (char*) malloc(sizeof(char) * (n+1));
            for (j = 0; j < n; j ++) temp_row[j] = save[i][j];
            temp_row[n] = '\0';
            temp[i] = temp_row;
        }
        al_add_last(l, temp);
        return;
    }
    for (col = 0; col < n; col ++) {
        if (valid(save, row, col, n)) {
            save[row][col] = 'Q';
            solve(l, save, row+1, n);
            save[row][col] = '.';
        }
    }
}

char*** solveNQueens(int n, int* r) {
    char** save = (char**) malloc(sizeof(char*) * n);
    char* save_row = NULL;
    int i = 0, j = 0;
    pal l = (pal) malloc(sizeof(sal));
    l->size = 0;
    l->capacity = 16;
    l->arr = (T*) malloc(sizeof(T) * l->capacity);
    for (i = 0; i < n; i ++) {
        save_row = (char*) malloc(sizeof(char) * (n+1));
        for (j = 0; j < n; j ++) save_row[j] = '.';
        save_row[n] = '\0';
        save[i] = save_row;
    }
    solve(l, save, 0, n);
    *r = l->size;
    return al_convert_to_array_free_l(l);
}


void solve2(pal l, char** save, int row, int n, int* col_sign, int* lup_sign, int* rup_sign) {
    char** temp = NULL, *temp_row = NULL;
    int i = 0, j = 0, col = 0;
    if (row == n) {
        temp = (char**) malloc(sizeof(char*) * n);;
        for (i = 0; i < n; i ++) {
            temp_row = (char*) malloc(sizeof(char) * (n+1));
            for (j = 0; j < n; j ++) temp_row[j] = save[i][j];
            temp_row[n] = '\0';
            temp[i] = temp_row;
        }
        al_add_last(l, temp);
        return;
    }
    for (col = 0; col < n; col ++) {
        if (!col_sign[col] && !lup_sign[col - row + n - 1] && !rup_sign[row + col]) {
            col_sign[col] = lup_sign[col - row + n - 1] = rup_sign[row + col] = 1;
            save[row][col] = 'Q';
            solve2(l, save, row+1, n, col_sign, lup_sign, rup_sign);
            save[row][col] = '.';
            col_sign[col] = lup_sign[col - row + n - 1] = rup_sign[row + col] = 0;
        }
    }
}

char*** solveNQueens2(int n, int* r) {
    char** save = (char**) malloc(sizeof(char*) * n);
    char* save_row = NULL;
    int i = 0, j = 0;
    pal l = (pal) malloc(sizeof(sal));
    int *col_sign = NULL, *lup_sign = NULL, *rup_sign = NULL; 
    l->size = 0;
    l->capacity = 16;
    l->arr = (T*) malloc(sizeof(T) * l->capacity);
    col_sign = (int*) malloc(sizeof(int) * n);
    lup_sign = (int*) malloc(sizeof(int) * (2 * n - 1));
    rup_sign = (int*) malloc(sizeof(int) * (2 * n - 1));
    for (i = 0; i < n; i ++) col_sign[i] = 0;
    for (i = 0; i < 2 * n - 1; i ++) lup_sign[i] = 0;
    for (i = 0; i < 2 * n - 1; i ++) rup_sign[i] = 0;
    for (i = 0; i < n; i ++) {
        save_row = (char*) malloc(sizeof(char) * (n+1));
        for (j = 0; j < n; j ++) save_row[j] = '.';
        save_row[n] = '\0';
        save[i] = save_row;
    }
    solve2(l, save, 0, n, col_sign, lup_sign, rup_sign);
    *r = l->size;
    free(col_sign);
    free(lup_sign);
    free(rup_sign);
    return al_convert_to_array_free_l(l);
}

int main() {
    int r = 0;
    int n = 13;
    int i = 0;
    int j = 0;
    char*** ans = NULL;
    for (n = 1; n < 7; n ++) {
        ans = solveNQueens2(n, &r);            
        printf("n is %d  r is %d\r\n", n, r);
        for (i = 0; i < r; i ++) {
            for (j = 0; j < n; j ++) {
                printf("%s\r\n", ans[i][j]);
                free(ans[i][j]);
            }
            printf("=======================\r\n");
        }
        free(ans);
    }
}


Python Solution: github

#coding=utf-8

'''
    url: leetcode.com/problems/n-queens
    @author:     zxwtry
    @email:      zxwtry@qq.com
    @date:       2017年4月9日
    @details:    Solution: 92ms 83.33%
'''

class Solution(object):
    def search(self, a, c, l, r, i, n, rec):
        if i == n:
            a_t,a_j=[],['.']*8
            for j in range(n):
                for j in range(n):
                    a_j[j]=(rec[j][j])
                a_t.append("".join(a_j))
            a.append(a_t)
            return
        for j in range(n):
            if not c[j] and not l[j+i] and not r[j-i+n-1]:
                c[j]=l[j+i]=r[j-i+n-1]=True
                rec[i][j]='Q'
                self.search(a, c, l, r, i+1, n, rec)
                c[j]=l[j+i]=r[j-i+n-1]=False
                rec[i][j]='.'
                
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        a,c,l,r=[],[False]*n,[False]*(2*n-1),[False]*(2*n-1)
        rec=[['.' for i in range(n)] for j in range(n)]
        self.search(a, c, l, r, 0, n, rec)
        return a

if __name__ == "__main__":
    print(Solution().solveNQueens(5))


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值