首先我们看看
1.归并排序写法
#include <iostream>
#include<vector>
#include <ctime>
#include<algorithm>
using namespace std;
#define num 100
void Merge(vector<int> &arr, int start, int end,int mid, vector<int> &temparr)
{
int i_start = start;
int i_end = mid;
int j_start = mid + 1;
int j_end = end;
int length = 0;
//合并两个有序序列(为什么就有序了) 思考!!!
while (i_start<= i_end&& j_start<= j_end)
{
if (arr[i_start]< arr[j_start])
{
temparr[length] = arr[i_start];
length++;
i_start++;
}
else
{
temparr[length] = arr[j_start];
length++;
j_start++;
}
}
while (i_start<= i_end)
{
temparr[length] = arr[i_start];
length++;
i_start++;
}
while (j_start <= j_end)
{
temparr[length] = arr[j_start];
length++;
j_start++;
}
//辅助空间数据覆盖到原空间
for (int i=0;i<length;i++)
{
arr[start+i]=temparr[i];
}
}
void MergeSort(vector<int> &arr, int start, int end, vector<int> &temparr)
{
if (start>=end)
{
return;
}
//划分到最后是每一个里面只有一个数据
int mid = (start + end) / 2;
MergeSort(arr,start,mid, temparr);
MergeSort(arr, mid+1, end, temparr);
Merge(arr, start, end, mid, temparr);
}
int main()
{
//int num;
//cin >> num;
vector<int> arr(num, 0);
srand((int)time(0));
for (int i = 0; i < num; i++)
{
arr[i] = rand() % 100;
}
for (int i = 0;i < arr.size();i++)
{
cout << arr[i] << " ";
}
cout << endl;
//归并排序(从小到大)
//由于归并排序需要申请额外空间大小,因空间复杂度是O(n)
vector<int> temparr(num, 0);
MergeSort(arr,0,arr.size() - 1,temparr);
for (int itemp : arr)
cout << itemp << " ";
return 0;
}
2.1然后再看看求某一个节点到根结点的长度
#include<iostream>
#include<vector>
using namespace std;
struct Node
{
int data;
Node * lchild;
Node * rchild;
};
vector<int> path;
bool flag2 = false;
void getNodePath(Node* root, int x) {
if (root == NULL) return;
if (flag2) return;
path.push_back(root->data);
if (root->data == x) {
for (int x : path) { //输出栈的内容
printf("%d ", x);
}
flag2 = true;
return;
}
getNodePath(root->lchild, x);
getNodePath(root->rchild, x);
path.pop_back();
}
拓展
2.1为了和后面的
全排列问题以及皇后问题进行统一
我们不妨改改,由于二叉数最多有两个孩子,后面的全排列以及皇后“孩子”可能有多个。
bool get_return(Node* &node,bool &flag,int x)
{
if (node->data == x) {
for (int x : path) { //输出栈的内容
printf("%d ", x);
}
flag = true;
}
return flag;
}
vector<int> path;
bool flag2 = false;
void getNodePath(Node* root, int x) {
if (root == NULL) return;
if (flag2) return; for (int i = 0;i < 1;i++)//由于二叉树最多只有两种可能 后面的全排列以及皇后是有多种可能的
{
if (i == 0)
{
if (get_return(root, flag2,x)==true)//理解为剪枝
{
return;
}
path.push_back(root->data);
getNodePath(root->lchild, x);
path.pop_back();
}
else
{
if (get_return(root, flag2, x) == true)理解为剪枝
{
return;
}
path.push_back(root->data);
getNodePath(root->rchild, x);
path.pop_back();
}
}
}
3.然后我们再看看,leetcode排列问题
首先我们写一种好理解的
class Solution {
private:
void dfs(int index,vector<int>& nums,vector<bool> &isUse_v,vector<vector<int>> &result_vv,vector<int>&temp_v)
{
if(index>=nums.size())
{
result_vv.push_back(temp_v);
return;
}
for(int i=0;i<nums.size();i++)
{
if(isUse_v[i]==true) continue;
temp_v.push_back(nums[i]);
isUse_v[i]=true;
dfs(index+1,nums,isUse_v,result_vv,temp_v);
isUse_v[i]=false;
temp_v.pop_back();
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>>result_vv;
vector<int>temp_v;
vector<bool> isUse_v(nums.size(),false);
dfs(0,nums,isUse_v,result_vv,temp_v);
return result_vv;
}
};
我们可以发现,我们必须申请比较多的变量才能跳过引用问题。
拓展
3.2因此我们使用引用后的写法;
根据leetcode自带函数写全排列,每次都传引用
class Solution {
private:
void dfs(int index,vector& nums,vector &isUse_v,vector> &result_vv,vector&temp_v)
{
if(index>=nums.size())
{
result_vv.push_back(temp_v);
return;
}
for(int i=0;i {
if(isUse_v[i]==true) continue;
temp_v.push_back(nums[i]);
isUse_v[i]=true; dfs(index+1,nums,isUse_v,result_vv,temp_v);
isUse_v[i]=false;
temp_v.pop_back();
}
}public:
vector> permute(vector& nums) {
vector>result_vv;
vectortemp_v;
vector isUse_v(nums.size(),false);
dfs(0,nums,isUse_v,result_vv,temp_v);
return result_vv;
}
};
**4.**说到这里就不得不提 leetcode全排列(有重复) 只需要剪枝就可以了
代码是根据上面代码改的
class Solution {
private:
void dfs(int index,vector<int>& nums,vector<bool> &isUse_v,vector<vector<int>> &result_vv,vector<int>&temp_v)
{
if(index>=nums.size())
{
result_vv.push_back(temp_v);
return;
}
for(int i=0;i<nums.size();i++)
{
if(isUse_v[i]==true) continue;
//就是相邻重复元素只需要遍历一次就可以了。
//isUse_v[i-1]==false与isUse_v[i-1]==true 在下面if中都是可以了,两种意义是不同的,一个是同层剪枝,一个上下剪枝
if(i>0&&nums[i]==nums[i-1]&&isUse_v[i-1]==false) continue;
temp_v.push_back(nums[i]);
isUse_v[i]=true;
dfs(index+1,nums,isUse_v,result_vv,temp_v);
isUse_v[i]=false;
temp_v.pop_back();
}
}
**5.**当然还有个经典的N皇后问题
N皇后问题问题来了
//回溯+dfs
class Solution {
//首先输出有多少可能
private:
void dfs(int index,int N,vector<int> &rowToclumn,vector<vector<string>> &result_vv)
{
if(index>=N)
{
//我们使用简单点的
vector<string> temp_v;
for(int i=0;i<N;i++)
{
string temp(N,'.');
int Q_index=rowToclumn[i];
temp.replace(Q_index,1,"Q");
// temp[Q_index]='Q';
temp_v.push_back(temp);
}
result_vv.push_back(temp_v);
}
for(int i=0;i<N;i++)
{
//cout<<"i="<<i<<" ";
if(getLegal(rowToclumn,index ,i)==false) continue;//与前面的皇后有冲突,就进行下一个位置的判定
rowToclumn.push_back(i);//这个就相当于全排列中,对于每个元素是否使用过,起到是否符合条件作用
dfs(index+1,N,rowToclumn,result_vv);
rowToclumn.pop_back();//与push相对应
}
}
bool getLegal( vector<int> rowToclumn,int row,int colum)//这个代表判断每个是不是 其中每个皇后都不同行、不同列,也不在对角线上
{
for(int one_row=0;one_row<rowToclumn.size();one_row++)
{
if(rowToclumn[one_row]==colum||(one_row+rowToclumn[one_row])==(row+colum)||(one_row-rowToclumn[one_row])==(row-colum))
return false;
}
return true;
}
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> result_vv;
//简单点
vector<int> rowToclumn;
dfs(0,n,rowToclumn,result_vv);
for(auto it=rowToclumn.begin();it!=rowToclumn.end();it++)
{
cout<<*it<< " ";
}
return result_vv;
}
};
6.组合问题
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
示例:
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
代码:
class Solution {
private:
vector<vector<int>> result_vv;
vector<int> restore;//存数据的
void _combine(int k,vector<int> &nums,int current_index)
{
//N是代表个数
//nums是代表着数据源
//current_index是代表现在访问的位置
if(restore.size()==k)
{
result_vv.push_back(restore);
return ;
}
for(int i=current_index;i<nums.size();i++)
{
restore.push_back(nums[i]);
//current_index;//组合问题就是这样
_combine(k,nums,i+1);
restore.pop_back();
}
return;
}
public:
vector<vector<int>> combine(int n, int k)
{
vector<int> restore;
vector<int> nums;
for(int i=0;i<n;i++)
{
nums.push_back(i+1);
}
int current_index=0;
_combine(k, nums,current_index);//0代表从第0位置搜索
return result_vv;
}
};