回溯与递归+分治 3/26

今日:刷题真痛苦
八皇后
求逆序数
树的字段和

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

上代码
/**
 * 八皇后问题,初始化,放,递归搜索
 */

/**
 * 初始化一个 queen,mark 表示一个棋盘 N*N,location 表示一个queen的点状图,result 存储最终结果
 * [".Q..",  location是这种点阵表达的,一个状态.初始都是"."
    "...Q",
    "Q...",
    "..Q."]
 *
 * ["1110",  mark 表示棋盘,初始都是0
    "1111",
    "1110",
    "0101"]

 *  初始化一组皇后数据
 */
std::vector<std::vector<string>> getQueen(int n) {
	std::vector<std::vector<string>> result;
	std::vector<string> location;
	std::vector<std::vector<int>> mark;

	for (int i = 0; i < n; i++)
	{
		mark.push_back((std::vector<int> ()));
		for (int j = 0; j < n; j++)
		{
			mark[i][j] = 0;
		}
		string temp(n,".");
		location.push_back(temp);
	}

	generateQueen(0, n, location, mark, result);
}

/**
 * 放置皇后,同时更新棋盘,前后左右中斜都要置1
 * 八个坐标位置(x,y)是 queen,下面用dx,dy来表示对应的x,y 坐标移动,对应的下标里面的值就是 X与 Y 想加的值
   (x-1,y-1)  (x-1,y)     (x-1,y+1)
   (x,y-1)     (x,y)      (x,y+1)
   (x+1,y-1)   (x+1,y)    (x+1,y+1)
 */
void putQueen(int x, int y, std::vector<std::vector<int>> &mark) {
    static const int dx[] = {-1,-1,-1, 0, 0, 1, 1, 1};
    static const int dy[] = {-1, 0, 1,-1, 1,-1, 0, 1};

    mark[x][y] = 1;

    //每一行都向皇后周围八个方向扩展置1
    for (int k = 1; k < mark.size(); k++) {
    	for (int j = 0; j < 8; j++) {
    		int newX = x + i*dx[j];
    		int newY = y + i*dy[j];
    		if (newX>=0 && newX < mark.size() && newY >=0 && newY < mark.size()) {
    			mark[newX][newY] = 1;
    		}
    	}
    }
}

/**
 * 递归放置棋盘,i 标识行号,n 是列,mark 标识棋盘状态,result 最终结果数组 N行 N 列的8皇后
 * 
 */

void generateQueen(int i, int n, std::vector<string> &location, std::vector<std::vector<int>> &mark, std::vector<std::vector<string>> &result) {
	//i放到最后一行了,就返回当前location
	if (i == n) {
	 	result.push_back(location);
	 	return;
	}

	//循环 n 列
	for (int k = 0; k < n; k++) {
		//当前可以放 QUEEN
		if (mark[i][k] == 0) {
			std::vector<std::vector<int>> temp_mark = mark;
			location[i][k] = 'Q';
			putQueen(i,k,mark);
			generateQueen(i+1, k, location, mark, result);
			location[i][k] = '.';
			mark = temp_mark;
		}
	}
}

在这里插入图片描述

/**
 * 逆序数,计算右侧小于当前元素的个数,归并排序
 */

 vector<int> countSmaller(vector<int>& nums) {
 	std::vector<int> result;
 	std::vector<pair<int, int>> vec;
 	for (int i=0;i<nums.size();i++) {
 		vec.push_back(make_pair(nums[i], i));
 	}


 }

//归并
void merge_sort(std::vector<pair<int,int>> &vec, std::vector<int> &result) {
	if (vec.size() < 2) {
		return;
	}
	int mid = vec.size();
	std::vector<pair<int, int>> vec1;
	std::vector<pair<int, int>> vec2;

	for (int i = 0; i < mid; i++)
	{
		vec1.push_back(vec[i]);
	}
	for (int i = mid; i < vec.size(); i++)
	{
		vec2.push_back(nums[i]);
	}

	merge_sort(vec1, result);
	merge_sort(vec2, result);
	vec.clear();
	merge_two_arr(vec1, vec2, vec, result);
}

//排序
void merge_two_arr(std::vector<pair<int,int>> &vec1, std::vector<pair<int, int>> &vec2, std::vector<int> &vec, std::vector<int> &result) {
	
	int i=0;
 	int j=0;

 	while(i < vec1.size() && j < vec2.size()) {
 		if(vec1[i].first < vec2[j].first) {
 			result[vec1[i].second] += j;
 			vec.push_back(vec1);
 			i++;
 		} else {
 			vec.push_back(vec2[j]);
 			j++;
 		}
 	}
 	for (;i < vec1.size(); i++)
 	{
 		result[vec1[i].second] += j;
 		vec.push_back(vec1);
 	}
 	for (;j < vec2.size(); j++)
 	{
 		vec.push_back(vec1);
 	}

}

树,双次递归,因为任意一个节点都可能是路径的头结点

/**
 * 树的路径和,给你一个key,求和等于key的路径,不一定是头或者尾节点
 */

int count = 0;
int getCount(BTree root, int key) {
	if (!root)
	{
		reutrn 0;
	}
	return count;
}

void solve(BTree root, int key) {
	if(!root) {
		return;
	}
	//先看看 root 节点为起始的序列中有没有
	dfs(root,key);
	//再分别以左右儿子为起点继续找
	solve(root->left, key);
	solve(root->right, key);
}

void dfs(BTree root, int sum) {
	if (!root) {
		return;
	}
	sum -= root->val;
	if (sum == 0) {
		count++;
	}
	dfs(root->left, sum);
	dfs(root->right, sum);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值