leetcode part4 递归、回溯、分治

/**
part4  递归  回溯 分治

递归函数基础:
    函数体内部出现了再次调用当前函数的语句
每个递归函数中都必须有递归结束/终止条件,当条件满足时,递归终止。

如: 用递归算法实现  1+2+3
**/
#include<iostream>
#include<vector>
using namespace std;

void compute_sum(int i,int &sum,int n){
    // 函数的参数sum为引用类型,则将形参传入时
    // 在函数体中对于形参的修改将直接体现在对传入参数的修改上
    if(i>n){
        return;
    }
    sum+=i;
    compute_sum(i+1,sum,n);
}

int main(){
    int sum=0;
    compute_sum(1,sum,3);
    cout<<"1+2+3=  "<<sum<<endl;
    return 0;
}
/**
递归函数应用:
    编写递归函数,实现功能:将链表中的数值按次序push到vector中
**/

#include<iostream>
#include<vector>
using namespace std;

struct ListNode{
    int val;
    ListNode *next;
    ListNode(int x):val(x),next(NULL){}
};

void add_to_vector(ListNode *head,vector<int> &vec){
    // & 表示传入的参数是引用类型,
    if(head==NULL){
        return;
    }
    vec.push_back(head->val);
    add_to_vector(head->next,vec);
}

int main(){
    ListNode a(1);
    ListNode b(2);
    ListNode c(3);
    ListNode d(4);
    ListNode e(5);

    a.next=&b;
    b.next=&c;
    c.next=&d;
    d.next=&e;

    vector<int> result;
    add_to_vector(&a,result);

    for(int i=0;i<result.size();i++){
        cout<<result[i]<<endl;
    }

    return 0;
}

/**
回溯法
    利用递归的思想解决问题的一种算法
    回溯法又称为试探法,但当探索到某一步时,发现原先选择
    达不到目标,就退回一步重新选择,这种走不通再退回的技术
    为回溯法
**/

学习算法的过程中,不能仅仅看视频学知识,还要多做相关的联系,以掌握算法。

#include<iostream>
#include<vector>
using namespace std;

/**
leetcode 78 子集
给定一组不含重复元素的整数数组 nums
返回该数组所有可能的子集(幂集)
说明:解集不能包含重复的子集
**/

class Solution {
public:
    vector<vector<int> > choose_n(vector<int>& nums,int n,int start_index){
        // 返回从nums数组中选择出n个元素的所有可能的组合形式
        // 如 choose([1,2,3],1,0)=[[1],[2],[3]]
        vector<vector<int> > output;
        if(n==0 or n>nums.size()){
            return output;
        }
        if(n==1){
            for(int i=start_index;i<nums.size();i++){
                vector<int> temp;
                temp.push_back(nums[i]);
                output.push_back(temp);
            }
            return output;
        }

        for(int i=start_index;i<nums.size();i++){
            vector<vector<int> > saved=this->choose_n(nums,n-1,i+1);
            for(int j=0;j<saved.size();j++){
                vector<int> temp;
                temp.push_back(nums[i]);
                temp.insert(temp.end(),saved[j].begin(),saved[j].end());
                output.push_back(temp);

                //cout<<"inside recurrion"<<endl;

            }
        }
        return output;
    }

    vector<vector<int> > subsets(vector<int>& nums) {
        vector<vector<int> > result;
        if(nums.size()==0){
            return result;
        }
        if(nums.size()==1){
            vector<int> temp;
            result.push_back(temp);
            result.push_back(nums);
            return result;
        }

        vector<int> c_n_0;
        result.push_back(c_n_0);

        for(int i=1;i<nums.size();i++){
            vector<vector<int> > output=this->choose_n(nums,i,0);
            result.insert(result.end(),output.begin(),output.end());
        }

        result.push_back(nums);
        return result;
    }
};

int main(){
    vector<int> input;
    for(int i=1;i<=3;i++){
        input.push_back(i);
    }
    Solution s;
    vector<vector<int> > result;
    result=s.subsets(input);

    for(int i=0;i<result.size();i++){
        for(int j=0;j<result[i].size();j++){
            cout<<result[i][j]<<"  ";
        }
        cout<<endl;
    }
    return 0;
}

/**
leetcode 78. 子集
方法2:利用位运算输出vector的所有子集
对vector中的元素按照index进行编码
  element     value   index  code
  vector[0]     1       0    001=1
  vector[1]     2       1    010=2
  vector[2]     3       2    100=4
对于所有包含3个元素的vector而言,共有2**3=8种子集
每个子集实际上都对应一个整数

**/
#include<iostream>
#include<vector>
using namespace std;

class Solution {
public:
    vector<vector<int> > subsets(vector<int>& nums){
        vector<vector<int> > result;
        if(nums.size()==0){
            return result;
        }
        if(nums.size()==1){
            vector<int> temp;
            result.push_back(temp);
            result.push_back(nums);
            return result;
        }

        int total_length=1<<nums.size();

//        cout<<total_length<<"here  "<<endl;

        // 表示最终输出的子集的长度
//        vector<int> encoded;
//        for(int i=0;i<nums.size();i++){
//            encoded.push_back(2<<i);
//        }
        // 根据索引下标的位置对输入的元素进行编码

        for(int i=0;i<total_length;i++){
            vector<int> temp;
            int temp_sum=i;
            for(int j=nums.size()-1;j>=0;j--){
                if(temp_sum<0){
                    break;
                }
                if(temp_sum>=1<<j){
                    temp.push_back(nums[j]);
                    temp_sum-=1<<j;
                }
            }
            result.push_back(temp);
        }
        return result;
    }
};

int main(){
    vector<int> input;
    for(int i=1;i<=3;i++){
        input.push_back(i);
    }
    Solution s;
    vector<vector<int> > result;
    result=s.subsets(input);

    for(int i=0;i<result.size();i++){
        for(int j=0;j<result[i].size();j++){
            cout<<result[i][j]<<"  ";
        }
        cout<<endl;
    }
    return 0;
}
/**
leetcode 90. 子集 II
给定一个可能包含重复元素的整数数组nums,
返回该数组所有可能的子集(幂集)

说明:解集不能包含重复的子集。

**/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

class Solution {
public:
    vector<vector<int> > choose_n(vector<int>& nums,int total,int start_index){
        vector<vector<int> > output;
        if(total==0 or start_index>=nums.size()){
            return output;
        }
        if(total==1){
            int i=start_index;
            while(i<nums.size()){
                vector<int> temp;
                temp.push_back(nums[i]);
                output.push_back(temp);

                i++;
                while(i<nums.size() and nums[i]==nums[i-1]){
                    i++;
                }
            }
            return output;
        }
        int k=start_index;
        while(k<nums.size()){
            vector<vector<int> > rec_output=this->choose_n(nums,total-1,k+1);
            for(int i=0;i<rec_output.size();i++){
                vector<int> temp;
                temp.push_back(nums[k]);
                temp.insert(temp.end(),rec_output[i].begin(),rec_output[i].end());
                output.push_back(temp);
            }
            k++;
            while(k<nums.size() and nums[k]==nums[k-1]){
                k++;
            }
        }
        return output;
    }

    vector<vector<int> > subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int> > result;

        if(nums.size()==0){
            return result;
        }
        if(nums.size()==1){
            vector<int> temp;
            result.push_back(temp);
            result.push_back(nums);
            return result;
        }

        // 在递归回溯的过程中进行去重
        vector<int> temp;
        result.push_back(temp);

        for(int i=1;i<nums.size();i++){
            vector<vector<int> > output;
            output=this->choose_n(nums,i,0);
            result.insert(result.end(),output.begin(),output.end());
        }
        result.push_back(nums);
        return result;

    }
};

int main(){
    vector<int> input;
    for(int i=1;i<=3;i++){
        input.push_back(i);
    }

    input[input.size()-1]--;

    Solution s;
    vector<vector<int> > result;
    result=s.subsetsWithDup(input);

    for(int i=0;i<result.size();i++){
        for(int j=0;j<result[i].size();j++){
            cout<<result[i][j]<<"  ";
        }
        cout<<endl;
    }
    return 0;
}

/**
leetcode 40. 组合总和 II
给定一个数组 candidates 和一个目标数 target
找出 candidates 中所有可以使数字和为 target 的组合
candidates 中的每个数字在每个组合中只能使用一次

说明:
    所有数字(包括目标数)都是正整数。
    解集不能包含重复的组合。


**/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

class Solution {
public:
    void find_sum(vector<vector<int> >& result,vector<int>& candidates,int target,int index){
        // 从candidates的初始索引为index开始,找到所有和为target的组合
        // 返回的组合序列的第一个元素必然是 candidates[index]
        if(target<=0 or candidates[index]>target){
            return;
        }

        if(candidates[index]==target){
            vector<int> temp;
            temp.push_back(candidates[index]);
            result.push_back(temp);
        }

        target=target-candidates[index];
        // 在递归函数内部进行去重
        int i=index+1;
        while(i<candidates.size()){
            if(candidates[i]>target){
                return;
            }
            else{
                vector<vector<int> > result_rec;
                this->find_sum(result_rec,candidates,target,i);

                for(int j=0;j<result_rec.size();j++){
                    vector<int> temp;
                    temp.push_back(candidates[index]);
                    temp.insert(temp.end(),result_rec[j].begin(),result_rec[j].end());
                    result.push_back(temp);
                }

                i++;
                while(i<candidates.size() and candidates[i]==candidates[i-1]){
                    i++;
                }
            }
        }
    }

    vector<vector<int> > combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int> > result;
        sort(candidates.begin(),candidates.end());

        if(candidates[0]>target){
            return result;
        }

        // 需要给子函数中的start_index参数赋值以进行去重
        int index=0;
        while(index<candidates.size()){
            vector<vector<int> > output;
            this->find_sum(output,candidates,target,index);

            result.insert(result.end(),output.begin(),output.end());
            index++;
            while(index<candidates.size() and candidates[index]==candidates[index-1]){
                index++;
            }
        }
        return result;
    }
};

int main(){
    int a[7]={10,1,2,7,6,1,5};
    vector<int> b;

    for(int i=0;i<7;i++){
        b.push_back(a[i]);
    }

    Solution s;
    vector<vector<int> > result=s.combinationSum2(b,8);

    for(int i=0;i<result.size();i++){
        for(int j=0;j<result[i].size();j++){
            cout<<result[i][j]<<" ";
        }
        cout<<endl;
    }


    return 0;
}


如何检查自己是否理解了某个代码:再做一些考查这个算法的编程题,看看是否能做得出来。

/**
leetcode 22. 括号生成
给出 n 代表生成括号的对数
请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

**/
#include<iostream>
#include<vector>
using namespace std;

class Solution {
public:
    void concrete_generate(int n,string str,int used_left,int used_right,vector<string>& result){

//        cout<<"each iteration: "<<str<<endl;
//
//        cout<<"used_left: "<<used_left<<"  used_right: "<<used_right<<endl;

        if(used_left<used_right){
            return;
        }

        // n:需要生成括号的对数,
        // 当前的字符串str,
        // used_left 当前的字符串中已经包含的左括号字符数
        // used_right 当前的字符串中已经包含的右括号字符数
        // result 输出的结果,最终输出的所有可能的字符串

        if(str.length()>n*2 or used_left>n or used_right>n){
            return;
        }

        if(str.length()==n*2 and used_left==n and used_right==n){
            result.push_back(str);

//            cout<<"-----------push_back: "<<str<<endl;

            return;
        }

        if(used_left==used_right and used_left<n){
//            string str1=str+"(";// 当左括号数量与右括号数量相等时,则只能添加左括号
//            vector<string> result_rec;
            this->concrete_generate(n,str+"(",used_left+1,used_right,result);

//            cout<<"here: "<<result_rec.size()<<endl;
//
//            for(int i=0;i<result_rec.size();i++){
//                result.push_back(str1+result_rec[i]);
//            }

            if(used_left>0){
                // 说明还可以添加右括号
//                string str2=str+")";
                //vector<string> result_rec2;
                this->concrete_generate(n,str+")",used_left,used_right+1,result);
//                for(int i=0;i<result_rec2.size();i++){
//                    result.push_back(str2+result_rec[i]);
//                }
            }
        }
        if(used_left>used_right){
            // 添加右括号
//            string str2=str+")";
//            vector<string> result_rec3;
            this->concrete_generate(n,str+")",used_left,used_right+1,result);
//            for(int i=0;i<result_rec3.size();i++){
//                result.push_back(str2+result_rec3[i]);
//            }
            if(used_left<n){
                // 添加左括号
//                string str4=str+"(";
                //vector<string> result_rec4;
                this->concrete_generate(n,str+"(",used_left+1,used_right,result);
//                for(int i=0;i<result_rec.size();i++){
//                    result.push_back(str4+result_rec[i]);
//                }
            }
        }
        return;
    }

    vector<string> generateParenthesis(int n) {
        vector<string> result;
        if(n==0){
            return result;
        }
        if(n==1){
            result.push_back("()");
            return result;
        }

        this->concrete_generate(n,"",0,0,result);
        return result;
    }
};

int main(){
    Solution s;
    vector<string> result;
    result=s.generateParenthesis(3);

    cout<<"total element: "<<result.size()<<endl;

    for(int i=0;i<result.size();i++){
        cout<<result[i]<<endl;
    }

    return 0;
}
#include<iostream>
#include<vector>
#include<string>
#include<stdlib.h>
using namespace std;

/**
leetcode 51. N皇后
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上
并且使皇后彼此之间不能相互攻击。

使用递归/回溯算法

这种算法的时间复杂度太高了,并没有对问题分析透彻就开始写代码了

**/

class Solution
{
public:
    vector<vector<string> > concrete_start(int n,int acc,int leave,int start_row,int start_col,vector<vector<int> > matrix_flag,vector<string> choose)
    {

//        cout<<"进入本次迭代...."<<start_row<<", "<<start_col<<endl;
        /**
        acc 表示累计到现在共有多少个queen被放置到了二维矩阵中
        start_row和start_col表示的就是当前步骤所需要选择放置queen的位置
        放置完成后,对matrix_flag的相应位置上做标记

        leave 表示当前的matrix_flag中还有多少个位置点是可以被放置的,即在安全范围内的
        **/
        if(leave<n-acc)
        {
            // 如果当前棋盘格上的没有攻击性的点数小于所需要的剩余点数,则说明无法构成
            vector<vector<string> > empty1;
            return empty1;
        }

        matrix_flag[start_row][start_col]=1;
        choose[start_row].replace(start_col,1,"Q");
        // 再将以当前位置辐射出去的所有位置范围内的位置点都变成1
        acc++;
        leave--;

        vector<vector<string> > result;
        if(acc==n)
        {
            // 如果choose中为'Q'的字符总数为n,则表示找到了以start_row和start_col为起始点的N皇后棋盘
            // 则choose有意义
            result.push_back(choose);
            return result;
        }


        // 将start_row所在的行变成1
        for(int i=start_col-1;i>=0;i--)
        {
            if(matrix_flag[start_row][i]==0){
                matrix_flag[start_row][i]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
        }

        for(int i=start_col+1;i<n;i++){
            if(matrix_flag[start_row][i]==0){
                matrix_flag[start_row][i]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
        }

        // 将start_col所在的列变成1
        for(int j=start_row-1; j>=0;j--){
            if(matrix_flag[j][start_col]==0){
                matrix_flag[j][start_col]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
        }

        for(int j=start_row+1; j<n;j++){
            if(matrix_flag[j][start_col]==0){
                matrix_flag[j][start_col]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
        }

        // 将主对角线45度所在的元素变成1
        int up_i=start_row-1;
        int up_j=start_col-1;

        while(up_i>=0 and up_j>=0){
            if(matrix_flag[up_i][up_j]==0){
                matrix_flag[up_i][up_j]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
            up_i--;
            up_j--;
        }

        up_i=start_row+1;
        up_j=start_col+1;
        while(up_i<n and up_j<n){
            if(matrix_flag[up_i][up_j]==0){
                matrix_flag[up_i][up_j]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
            up_i++;
            up_j++;
        }

        // 将次对角线上的所有元素变成1
        up_i=start_row-1;
        up_j=start_col+1;
        while(up_i>=0 and up_j<n){
            if(matrix_flag[up_i][up_j]==0){
                matrix_flag[up_i][up_j]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
            up_i--;
            up_j++;
        }

        up_i=start_row+1;
        up_j=start_col-1;
        while(up_i<n and up_j>=0){
            if(matrix_flag[up_i][up_j]==0){
                matrix_flag[up_i][up_j]=1;
                leave--;
//                if(leave<n-acc){
//                    return false;
//                }
            }
            up_i++;
            up_j--;
        }

//        cout<<"matrix_flag: "<<matrix_flag.size()<<", "<<matrix_flag[0].size()<<endl;

//        cout<<"n= "<<n<<endl;


        // 选作下一个放置皇后的坐标点必须是在当前的坐标点之后
        // 即将当前坐标点之前行所有坐标点都变成1
        // 并且将当前行此列之前的所有坐标点都变成1

        for(int i=0;i<=start_row;i++){
            for(int j=0;j<n;j++){
                if(matrix_flag[i][j]==0){
                    matrix_flag[i][j]=1;
                    leave--;
                }
            }
        }

        for(int i=0;i<start_col;i++){
            if(matrix_flag[start_row][i]==0){
                matrix_flag[start_row][i]=1;
                leave--;
            }
        }


        if(leave<n-acc){
            vector<vector<string> > empty1;
            return empty1;
        }


        vector<vector<string> > result_rec;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(matrix_flag[i][j]==0){

//                    cout<<"i:"<<i<<" j:"<<j<<endl;

                    result_rec=this->concrete_start(n,acc,leave,i,j,matrix_flag,choose);

//                    cout<<"完成本次迭代...."<<start_row<<", "<<start_col<<" flag= "<<flag<<endl;

                    if(result_rec.size()>0){
                        result.insert(result.end(),result_rec.begin(),result_rec.end());
                    }
                }
            }
        }
        return result;
    }

    vector<vector<string> > solveNQueens(int n)
    {
        vector<vector<string> > result;
        vector<vector<int> > had_chosen;// 表示当前的起始点已经被选择
        for(int i=0;i<n;i++){
            vector<int> temp2;
            for(int j=0;j<n;j++){
                temp2.push_back(0);
            }
            had_chosen.push_back(temp2);
        }

//        vector<string> init_choose;
//        vector<vector<int> > init_matrix_flag;
//        for(int k=0;k<n;k++){
//            string temp="";
//            vector<int> temp_line;
//            for(int p=0;p<n;p++){
//                temp+=".";
//                temp_line.push_back(0);
//            }
//            init_choose.push_back(temp);
//            init_matrix_flag.push_back(temp_line);
//        }

        vector<vector<string> > temp_result;

        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
//                if(had_chosen[i][j]==0){

//                    cout<<"start position: "<<i<<", "<<j<<endl;
                    vector<string> init_choose;
                    vector<vector<int> > init_matrix_flag;
                    for(int k=0;k<n;k++){
                        string temp="";
                        vector<int> temp_line;
                        for(int p=0;p<n;p++){
                            temp+=".";
                            temp_line.push_back(0);
                        }
                        init_choose.push_back(temp);
                        init_matrix_flag.push_back(temp_line);
                    }

                    //cout<<"选择了一个新的初始点: "<<i<<", "<<j<<endl;

                    temp_result=this->concrete_start(n,0,n*n,i,j,init_matrix_flag,init_choose);
                    if(temp_result.size()>0){
                        result.insert(result.end(),temp_result.begin(),temp_result.end());

                    }
//                }

                  cout<<"选择了一个新的初始点: "<<i<<", "<<j<<endl;
                  cout<<"以当前节点作为第一个点的可能情况"<<temp_result.size()<<endl;


            }
        }
        return result;
    }
};

int main(){

//    string a="aaaaa";
//    a.replace(0,1,"m");
//    // C++中的字符串string替换某个索引位置的字符需要使用replace函数
//    cout<<a<<endl;



    Solution s;
    vector<vector<string> > result;
    int n=9;
    result=s.solveNQueens(n);

    for(int i=0;i<result.size();i++){
        for(int j=0;j<result[i].size();j++){
            cout<<result[i][j]<<","<<endl;
        }
        cout<<endl;
    }

    cout<<result.size()<<endl;

    return 0;
}
#include<iostream>
#include<vector>
using namespace std;

/**
对问题进行具体分析后可以发现,
n*n矩阵的每一行都只能放置一个Queue,
每一列也只能放置一个Queue

必须要明确的几点是:
无论n为何值,N皇后问题至少包含1个解
    这意味着只需要迭代(循环考虑)第0行Queue所要放置的列即可
    故最外层循环需要循环N次

    循环考虑第0行所需要放置的位置,再观察后面的行可能放置的位置
**/

class Solution {
public:
    vector<vector<string> > pos_each_line(int line_num,int col,vector<int> choose_row,vector<int> choose_col,vector<bool> col_used,vector<string> choose){
        // line_num  表示当前所考虑的行数,从第0行开始
        // col 表示所选择需要放置的列数,
        // matrix_flag  选择在第line_num行、第col列放置queen之前,matrix_flag中为1的位置表示不能放置queen的非法位置
        // choose  表示在将queen放置到第line_num行、第col列之前,所选择的字符串

        //choose_row 表示在第line_num行之前所选择的所有行数
        //choose_col 表示在第line_num行之前所选择的所有列数

        int n=choose.size();
        // matrix_flag[line_num][col]=1;
        choose[line_num].replace(col,1,"Q");

        if(line_num==n-1){
            vector<vector<string> > result_rec;
            result_rec.push_back(choose);
            return result_rec;
        }

        if(line_num==n){
            vector<vector<string> > result_rec;
            //result_rec.push_back(choose);
            return result_rec;
        }

        choose_row.push_back(line_num);
        choose_col.push_back(col);

        col_used[col]=true;

        line_num++;

        // 下一行不能选择的列,为true则表示已经被前面的行选择过了
        vector<bool> invalid_col=col_used;
        for(int k=0;k<choose_col.size();k++){
            // 根据之前选择过的点的对角线关系,确定在当前的行中不能选择哪些列
            int pos_45=line_num+choose_col[k]-choose_row[k];
            if(pos_45>=0 and pos_45<n){
                invalid_col[pos_45]=true;
            }

            int neg_45=choose_col[k]+choose_row[k]-line_num;
            if(neg_45>=0 and neg_45<n){
                invalid_col[neg_45]=true;
            }
        }
        // 给出下一行所能选择的列

        vector<vector<string> > result;
        int invalid_num=0;

        vector<int> valid_col_set;

        for(int i=0;i<n;i++){
            if(invalid_col[i]!=true){
                valid_col_set.push_back(i);
            }
        }

        if(valid_col_set.size()==0){
            vector<vector<string> > result_rec;
            //result_rec.push_back(choose);
            return result_rec;
        }

        for(int i=0;i<valid_col_set.size();i++){
                // 说明在下一行可以选择当前列数
            vector<vector<string> > result_rec;
            result_rec=this->pos_each_line(line_num,valid_col_set[i],choose_row,choose_col,col_used,choose);
            if(result_rec.size()>0){
                result.insert(result.end(),result_rec.begin(),result_rec.end());
            }
        }

        return result;
    }

    vector<vector<string> > solveNQueens(int n) {
        vector<vector<string> > result;

        vector<string> init_choose;
        for(int i=0;i<n;i++){
            string temp="";
            for(int j=0;j<n;j++){
                temp+=".";
            }
            init_choose.push_back(temp);
        }

        vector<bool> col_used_init;
        for(int i=0;i<n;i++){
            col_used_init.push_back(false);
        }

        for(int i=0;i<n;i++){
            // i表示第0行所需要放置Queen的列数/位置
            vector<vector<string> > temp_result;

            vector<int> choose_row;
            vector<int> choose_col;
            vector<bool> col_used=col_used_init;
            // C++ 中的赋值运算符是deep copy,将会在内存空间中额外开辟存储空间存放col_used
            // 修改col_used的数值并不会影响col_used_init

            temp_result=this->pos_each_line(0,i,choose_row,choose_col,col_used,init_choose);
            if(temp_result.size()>0){
                result.insert(result.end(),temp_result.begin(),temp_result.end());
            }
        }
        return result;
    }
};

int main(){

//    string a="aaaaa";
//    a.replace(0,1,"m");
//    // C++中的字符串string替换某个索引位置的字符需要使用replace函数
//    cout<<a<<endl;



    Solution s;
    vector<vector<string> > result;
    int n=9;
    result=s.solveNQueens(n);

    for(int i=0;i<result.size();i++){
        for(int j=0;j<result[i].size();j++){
            cout<<result[i][j]<<","<<endl;
        }
        cout<<endl;
    }

    cout<<result.size()<<endl;

    return 0;
}

/**
归并两个已经排序的数组
已知两个已经排序的数组,将这两个数组合并为一个排序数组

分治算法:
    将一个规模为N的问题分解为K个规模较小的子问题
    这些子问题相互独立且与原问题性质相同
    求出子问题的解后进行合并,就可得到原问题的解

一般步骤:
    将原问题分解成若干规模较小的同类问题
    当子问题被划分得足够小时,用较简单的方法求解(递归函数的递归基)
    合并:将子问题的解逐层和并构成原问题的解
在代码中体现为:
    递归基的解(当问题的规模被划分得足够小时,用简单的方法即可得到问题的解)
    对大规模的原问题进行划分,划分成K个规模较小的子问题
    对K个子问题分别进行求解
    对K个子问题的解进行合并
**/

#include<vector>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;

void merge_sort_two_vec(vector<int> &sub_vec1,vector<int> &sub_vec2,vector<int> &vec){
    int i=0;
    int j=0;

    while(i<sub_vec1.size() and j<sub_vec2.size()){
        if(sub_vec1[i]<=sub_vec2[j]){
            vec.push_back(sub_vec1[i]);
            i++;
        }
        else{
            vec.push_back(sub_vec2[j]);
            j++;
        }
    }
    for(;i<sub_vec1.size();i++){
        vec.push_back(sub_vec1[i]);
    }
    for(;j<sub_vec2.size();j++){
        vec.push_back(sub_vec2[j]);
    }
}

void merge_sort(vector<int> &vec){
    // 对输入的vector进行归并排序
    // 归并排序的时间复杂度为O(NlogN)
    if(vec.size()<=1){
        return;// 当子问题的规模足够小时,直接求解
    }

    int mid=vec.size()/2;
    // 对原问题进行分解,即对原数组拆分为两个规模相同的数组
    // 再对它们分别进行排序
    vector<int> sub_vec1;
    vector<int> sub_vec2;

    for(int i=0;i<mid;i++){
        sub_vec1.push_back(vec[i]);
    }

    for(int j=mid;j<vec.size();j++){
        sub_vec2.push_back(vec[j]);
    }
    merge_sort(sub_vec1);
    merge_sort(sub_vec2);
    vec.clear();// 将vec向量进行清空
    merge_sort_two_vec(sub_vec1,sub_vec2,vec);// 将子问题的解进行合并
}

int main(){
//    vector<int> sub_vec1;
//    vector<int> sub_vec2;
//
//    sub_vec1.push_back(2);
//    sub_vec1.push_back(5);
//    sub_vec1.push_back(8);
//    sub_vec1.push_back(20);
//
//    sub_vec2.push_back(1);
//    sub_vec2.push_back(3);
//    sub_vec2.push_back(5);
//    sub_vec2.push_back(7);
//    sub_vec2.push_back(30);
//    sub_vec2.push_back(50);
//
//    vector<int> vec;
//
//    merge_sort_two_vec(sub_vec1,sub_vec2,vec);

//    vector<int> vec;
//    vec.push_back(5);
//    vec.push_back(1);
//    vec.push_back(4);
//    vec.push_back(2);
//    vec.push_back(3);

//    int test1[]={-5,-7,9,8,1,4,-3,10,2,0};
//    for(int i=0;i<10;i++){
//        vec.push_back(test1[i]);
//    }

    vector<int> vec1;
    vector<int> vec2;

    srand(0);
    // srand() 函数功能:初始化随机数发生器
    // srand(int ) 传入的int类型整数用来设置rand()产生随机数时的随机种子
    // rand() 函数不需要任何参数,它会返回一个从0到最大随机数的任意整数,
    // 最大随机数的大小通常是固定的一个大整数
    // 如果需要产生的随机数在0-100之间,则只需要rand()%101 即可
    
    for(int i=0;i<10000;i++){
        int num=(rand()*rand())/100003;
        vec1.push_back(num);
        vec2.push_back(num);
    }

    merge_sort(vec1);

    sort(vec2.begin(),vec2.end());

    assert(vec1.size()==vec2.size());

    for(int i=0;i<vec1.size();i++){
        assert(vec1[i]==vec2[i]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值