返回顶部

A 第四课 递归_回溯_分治

内容概述及预备知识

 

预备知识:递归函数与回溯算法

#include <iostream>
#include <vector>

using namespace std;

class ListNode{
public:
int val;
ListNode * next;
ListNode(int x):val(x),next(NULL){
}
};
// 将 链表中的 数据递归加入到 vector 中
void addToVec(ListNode* header,vector<int>& vec){
// 递归条件
if(header == NULL){
return;
}
vec.push_back(header->val);
// 递归链条
addToVec(header->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> vec;
addToVec(&a,vec);

// 遍历 vec
for(auto it=vec.cbegin();it!=vec.cend();it++){
cout << *it << " ";
}
cout << endl;

return 0;
}
递归小练习(结合链表)

 

 

 

回溯法:

回溯一般要用递归来实现,

 

例1-a:求子集(LeetCode No.78 )

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

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

示例:

输入: nums = [1,2,3]
输出:
[
[3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

 

思路及代码

 

1,循环,不容易往后退, 

2, 如何生成  [1] ,[1,2]  [1,2,3] ,

#include <iostream>
#include <vector>

using namespace std;

int main(){
vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);


// 生成item :type is vector<int>
int size = nums.size();
vector<int> item;
vector<vector<int>> result;
for(int i=0;i<size;i++){
item.push_back(nums[i]);
result.push_back(item);
}
// 打印 result
for(auto it= result.cbegin();it!=result.cend();it++){
for(auto it2 = (*it).cbegin();it2!=(*it).cend();it2++){
cout << *it2<<" ";
}
cout << endl;
}

return 0;
}
/*
1
1 2
1 2 3
*/
循环生成
#include <iostream>
#include <vector>

using namespace std;

void generate(int idx,vector<int>& nums,vector<int>& item,vector<vector<int>>& result){

// 递归条件
if(idx > (int)nums.size() - 1){
return;
}
item.push_back(nums[idx]);
result.push_back(item);
// 递归链条
generate(idx+1,nums,item,result);
return;
}

int main(){
vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);

vector<int> item;
vector<vector<int>> result;

// 递归生成 result
generate(0,nums,item,result);

// 打印 result
for(auto it= result.cbegin();it!=result.cend();it++){
for(auto it2 = (*it).cbegin();it2!=(*it).cend();it2++){
cout << *it2<<" ";
}
cout << endl;
}

return 0;
}
/*
1
1 2
1 2 3
*/
递归生成

 

 

算法思路:

 

#include <iostream>
#include <vector>

using namespace std;


void generate(int idx,vector<int>nums,vector<int>& item,vector<vector<int>>& res){

// 递归条件
if(idx > (int)nums.size() -1){
return;
}
item.push_back(nums[idx]);
res.push_back(item);

// 递归链条 (第一次递归)
generate(idx+1,nums,item,res);
item.pop_back();
// 递归链条 (第二次递归)
generate(idx+1,nums,item,res);

}


vector<vector<int>> subsets(vector<int>& nums) {

vector<int> item;
vector<vector<int>> res;
res.push_back(item); // 将空集 push 进去
generate(0,nums,item,res);

return res;
}

int main(){
vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);
nums.push_back(4);

vector<vector<int>> ret = subsets(nums);




// 打印 ret
for(auto it= ret.cbegin();it!=ret.cend();it++){
for(auto it2 = (*it).cbegin();it2!=(*it).cend();it2++){
cout << *it2<<" ";
}
cout << endl;
}
return 0;
}
View Code

 

 

方法二:位运算法:

 

#include <iostream>
#include <vector>

using namespace std;

vector<vector<int>> subsets(vector<int>& nums) {

vector<vector<int>> res;
int size = nums.size();
int totalNum = 1 << size; // 1<< n 即 2^n
for(int i=0;i<totalNum;i++){
vector<int> item;
for(int j= 0;j<size;j++){ // 遍历nums中元素,
// 使用元素对应的整数 和 i 比较
if(i & 1<<(size - j - 1)){ // [a,b,c] // a:100 b:100 c:001
item.push_back(nums[j]);
}
}
res.push_back(item);
}

return res;
}

int main(){
vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);

vector<vector<int>> ret = subsets(nums);

// 打印 ret
for(auto it= ret.cbegin();it!=ret.cend();it++){
for(auto it2 = (*it).cbegin();it2!=(*it).cend();it2++){
cout << *it2<<" ";
}
cout << endl;
}
return 0;
}
View Code

 

 

 

 

例1-b:求子集2(LeetCode No.90)

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

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

示例:

输入 nums = [1,2,2] 

 按上面的算法结果是:

1
1 2
1 2 2
1 2
2
2 2
2

注意:结果中1,2  和 1,2 重复, 

思考和代码:

 

 

 

#include <iostream>
#include <set>
#include <vector>
#include <algorithm>

using namespace std;


void generate(int idx,vector<int>nums,vector<int>& item,vector<vector<int>>& res,set<vector<int>> & res_set){

    // 递归条件
    if(idx > (int)nums.size() -1){
        return;
    }
    item.push_back(nums[idx]);
    if(res_set.find(item) == res_set.end()){ // 如果 在res_set 中 不能找到 item 
        res.push_back(item);
        res_set.insert(item);
    }
    
    // 递归链条 (第一次递归)
    generate(idx+1,nums,item,res,res_set);
    item.pop_back();
    // 递归链条 (第二次递归)
    generate(idx+1,nums,item,res,res_set);

}


vector<vector<int>> subsets(vector<int>& nums) {

    vector<int> item;
    vector<vector<int>> res;
    set<vector<int>> res_set; // 去重用的集合
    sort(nums.begin(),nums.end()); // 排序 

    res.push_back(item); // 将空集 push 进去
    generate(0,nums,item,res,res_set);

return res;
}

int main(){
vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(2);

vector<vector<int>> ret = subsets(nums);




// 打印 ret
for(auto it= ret.cbegin();it!=ret.cend();it++){
for(auto it2 = (*it).cbegin();it2!=(*it).cend();it2++){
cout << *it2<<" ";
}
cout << endl;
}
return 0;
}
View Code

 

 

例1-c:组合数之和2(LeetCode No.40)

 

 

思路及代码

 

#include <iostream>
#include <set>
#include <vector>
#include <algorithm>

using namespace std;


void generate(int idx,vector<int>nums,vector<int>& item,vector<vector<int>>& res,set<vector<int>> & res_set){

    // 递归条件
    if(idx > (int)nums.size() -1){
        return;
    }
    item.push_back(nums[idx]);
    if(res_set.find(item) == res_set.end()){ // 如果 在res_set 中 不能找到 item 
        res.push_back(item);
        res_set.insert(item);
    }
    
    // 递归链条 (第一次递归)
    generate(idx+1,nums,item,res,res_set);
    item.pop_back();
    // 递归链条 (第二次递归)
    generate(idx+1,nums,item,res,res_set);

}


vector<vector<int>> subsets(vector<int>& nums,int target) {

    vector<int> item;
    vector<vector<int>> res;
    set<vector<int>> res_set; // 去重用的集合
    sort(nums.begin(),nums.end()); // 排序 

    res.push_back(item); // 将空集 push 进去
    generate(0,nums,item,res,res_set);

    vector<vector<int>> target_res; // 存储最终的结果 
    for(int i=0;i<(int)res.size();i++){
        int sum = 0;
        for(int j =0;j<(int)res[i].size();j++){
            sum += res[i][j];
        }
        if(sum == target){
            target_res.push_back(res[i]);
        }
    }
    return target_res;
}

int main(){
vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(2);

vector<vector<int>> ret = subsets(nums);




// 打印 ret
for(auto it= ret.cbegin();it!=ret.cend();it++){
for(auto it2 = (*it).cbegin();it2!=(*it).cend();it2++){
cout << *it2<<" ";
}
cout << endl;
}
return 0;
}
在1-b 的基础上,提交超时

 

如何解决上面的问题,通过剪枝

 

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

void generate(int idx,vector<int>& nums,vector<int>& item,vector<vector<int>>& res,set<vector<int>>& res_set,int sum,int target){
    int size = nums.size();
    // base case 
    if(idx > size -1 || sum > target){
        return;
    }
    item.push_back(nums[idx]);
    sum += nums[idx];
    
    if(sum == target && res_set.find(item) == res_set.cend()){ // 在res_set 中没找到 item
        res_set.insert(item);
        res.push_back(item);
    }

    // 递归链条(第一次)
    generate(idx+1,nums,item,res,res_set,sum,target);
    item.pop_back(); // 回溯 
    sum -= nums[idx];

    // 递归链条(第一次)
    generate(idx+1,nums,item,res,res_set,sum,target);
}

vector<vector<int>> subsets(vector<int>& nums,int target){
    sort(nums.begin(),nums.end());

    vector<int> item;
    vector<vector<int>> res;
    set<vector<int>> res_set;

    generate(0,nums,item,res,res_set,0,target);

    return res;
}


int main(){
    vector<int> nums;
    nums.push_back(1);
    nums.push_back(3);
    nums.push_back(2);

    vector<vector<int>> ret;
    ret = subsets(nums,4);

    // 打印
    for(auto it1 = ret.cbegin();it1!=ret.cend();it1++){
        for(auto it2 = (*it1).cbegin();it2!=(*it1).cend();it2++){
            cout <<*it2<<" ";
        }
        cout << endl;
    }




    return 0;
}
View Code

 

 

例2:生成括号(LeetCode No.22)

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

 

示例:

输入:n = 3
输出:[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]

 

思路及代码

思考:

 

 

#include <iostream>
#include <vector>
#include <string>

using namespace std;


void generate(string item,int n,vector<string>& res){
    // base case 
    int size= item.size();
    if(size == 2*n){
        res.push_back(item);
        return;
    }

    // 递归链条 
    generate(item+"(",n,res);
    generate(item+")",n,res);

}

int main(){

    vector<string> ret;

    generate("",2,ret); //2 组括号 

    for(auto it=ret.cbegin();it!=ret.cend();it++){
        cout << *it << endl;
    }


    return 0;
}

/* output
((((
((()
(()(
(())
()((
()()
())(
()))
)(((
)(()
)()(
)())
))((
))()
)))(
))))

*/
View Code

 

合法性:

 

#include <iostream>
#include <vector>
#include <string>

using namespace std;


void generate(string item,int n,vector<string>& res,int lfNum,int rtNum){ // lf rt为 左右括号的个数
    // base case 
    int size= item.size();
    if(lfNum > n || rtNum >n){ // 肯定是不合法的 
        return;
    }
    if(size == 2*n){
        res.push_back(item);
        return;
    }

    // 递归链条 
    generate(item+"(",n,res,lfNum+1,rtNum);

    if(lfNum > rtNum){ // 此时才能进行 右括号的添加
        generate(item+")",n,res,lfNum,rtNum+1);
    }

}

int main(){

    vector<string> ret;

    generate("",2,ret,0,0); //2 组括号 

    for(auto it=ret.cbegin();it!=ret.cend();it++){
        cout << *it << endl;
    }


    return 0;
}
我的代码

 

class Solution {
private:
void generate(string item,int lfNum,int rtNum,vector<string>& res){ // lf rt为 当前还可以放置的数量 


    if(lfNum == 0 && rtNum == 0){
        res.push_back(item);
        return;
    }
    if(lfNum >0){
        generate(item+"(",lfNum-1,rtNum,res);
    }
    if(lfNum<rtNum){
        generate(item+")",lfNum,rtNum-1,res);
    }

}
public:
    vector<string> generateParenthesis(int n) {
      vector<string> ret;
      generate("",n,n,ret);
      return ret;
    }
};
ls 代码

 

 

例3:N皇后(LeetCode No.51)

 

 

思路及代码

皇后的攻击范围:

 

棋盘和皇后表示:

放完皇后如何更新棋盘?(通过方向数组解决)

 

#include <iostream>
#include <vector>

using namespace std;

void put_down_the_queen(int x,int y,vector<vector<int>>& mark){
    // 方向数组 
    static const int dx[] = {-1,1,0,0,-1,-1,1,1};// dx 和dy 要对应
    static const int dy[] = {0,0,-1,1,-1,1,-1,1};

    mark[x][y] = 1;
    int size = mark.size();
    for(int i=1;i<size;i++){

        for(int j=0;j<8;j++){
            int newX = x+i*dx[j];
            int newY = y+i*dy[j];
            if(newX>=0&&newX<size && newY>=0&&newY<size){
                mark[newX][newY] = 1;
            }
        }
    }

}



void myPrint(vector<vector<int>> mark){
    for(int i=0;i<8;i++){
        for(int j=0;j<8;j++){
            cout <<mark[i][j]<< " ";
        }
        cout << endl;
    }

}

int main(){
    vector<vector<int>> mark;
    // 生成 mark  
    vector<int> temp;
    for(int i=0;i<8;i++){
        for(int j=0;j<8;j++){
            temp.push_back(0);
        }
        mark.push_back(temp);
        temp.clear();
    }

    // 打印 mark  
    myPrint(mark);
    cout << "======put the queen to the pos(3,2)====="<< endl;
    
    // 放置皇后, 更新 mark 
    put_down_the_queen(3,2,mark); // 放在 4行 3列

    // 打印 mark  
    myPrint(mark);


    return 0;
}

/* output:
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
======put the queen to the pos(3,2)=====
0 0 1 0 0 1 0 0 
1 0 1 0 1 0 0 0 
0 1 1 1 0 0 0 0 
1 1 1 1 1 1 1 1 
0 1 1 1 0 0 0 0 
1 0 1 0 1 0 0 0 
0 0 1 0 0 1 0 0 
0 0 1 0 0 0 1 0 
*/
View Code

 

算法思路:

 

用递归放皇后到每一行,然后回溯列(放在该列,完成后再尝试不放在该列)

#include <iostream>
#include <vector>

using namespace std;

void put_down_the_queen(int x,int y,vector<vector<int>>& mark){
    // 方向数组 
    static const int dx[] = {-1,1,0,0,-1,-1,1,1};// dx 和dy 要对应
    static const int dy[] = {0,0,-1,1,-1,1,-1,1};

    mark[x][y] = 1;
    int size = mark.size();
    for(int i=1;i<size;i++){
        for(int j=0;j<8;j++){
            int newX = x+i*dx[j];
            int newY = y+i*dy[j];
            if(newX>=0&&newX<size && newY>=0&&newY<size){
                mark[newX][newY] = 1;
            }
        }
    }

}
void generate(int idx,int n,vector<string>& item,vector<vector<string>>& res,vector<vector<int>>& mark){ // 放置idx 皇后 ,总共n个皇后 

    // base case  
    if(idx > n-1){
        res.push_back(item);
        return;
    }

    // 一一尝试 n 列 
    for(int i=0;i<n;i++){
        if(mark[idx][i] == 0){ // 此时可以 放置皇后 
            vector<vector<int>> temp_mark = mark; // 备份 mark
            item[idx][i] = 'Q';
            put_down_the_queen(idx,i,mark);

            // 递归链条 
            generate(idx+1,n,item,res,mark); // 递归下一行 皇后

            // 回溯
            mark = temp_mark;
            item[idx][i] = '.';
        }
    }

}

vector<vector<string>> solveNQueens(int n){
    vector<vector<string>>res; // 最终的结果 
    vector<vector<int>> mark; // 标记棋盘的 二维数组 

    vector<string> item; // 存储 某个结果 

    // 初始化 mark 和 item
    for(int i=0;i<n;i++){
        mark.push_back(vector<int>());
        for(int j=0;j<n;j++){
            mark[i].push_back(0); // 初始 mark
        }
        // 初始化 item 
        item.push_back("");
        item[i].append(n,'.'); // item[0] = n个 点 
    }

    generate(0,n,item,res,mark);

    return res;
}
void myPrint(vector<vector<string>>& ret){
    for(int i=0;i<(int)ret.size();i++){
        for(int j=0;j<(int)ret[i].size();j++){
            cout <<ret[i][j]<<endl;;
        }
        cout << "=========" <<  endl;
    }
}

int main(){
    vector<vector<string>> ret = solveNQueens(4);

    myPrint(ret);

    return 0;
}

/*
.Q..
...Q
Q...
..Q.
=========
..Q.
Q...
...Q
.Q..
=========
*/
View Code

 

预备知识:分治算法与归并排序

 

 

代码实现:

#include <iostream>
#include <vector>

using namespace std;

void mergeTwoSortedVec(vector<int>& vec1,vector<int>& vec2,vector<int>& res ){

    int i = 0;
    int j = 0;
    int size1 = vec1.size();
    int size2 = vec2.size();
    while(i<size1 && j<size2){
        if(vec1[i] <= vec2[j]){ // 相等的话,放到前一个数组
            res.push_back(vec1[i]);
            i++;
        }else{
            res.push_back(vec2[j]);
            j++;
        }
    }
    // 将 vec1 和 vec2 剩余的元素 push 进 res
    for(;i<size1;i++){
        res.push_back(vec1[i]);
    }
    
    for(;j<size2;j++){
        res.push_back(vec2[j]);
    }
}






void myPrint(vector<int> vec){
    for(auto it = vec.cbegin();it != vec.cend();it++){
        cout <<*it << " ";
    }
    cout << endl;
}

int main(){

    vector<int> vec1 = {2,5,8,20};
    vector<int> vec2 = {1,3,5,7,30,50};
    vector<int> res;
    myPrint(vec1);
    myPrint(vec2);
    mergeTwoSortedVec(vec1,vec2,res);

    myPrint(res);


    return 0;
}
对两个有序数组进行归并排序

 

分治算法 排序

 

分治算法的时间复杂度:

 

 

#include <iostream>
#include <vector>

using namespace std;

void mergeTwoSortedVec(vector<int>& vec1,vector<int>& vec2,vector<int>& res ){

    int i = 0;
    int j = 0;
    int size1 = vec1.size();
    int size2 = vec2.size();
    while(i<size1 && j<size2){
        if(vec1[i] < vec2[j]){ 
            res.push_back(vec1[i]);
            i++;
        }else{
            res.push_back(vec2[j]);
            j++;
        }
    }
    // 将 vec1 和 vec2 剩余的元素 push 进 res
    for(;i<size1;i++){
        res.push_back(vec1[i]);
    }
    
    for(;j<size2;j++){
        res.push_back(vec2[j]);
    }
}

void mergeSort(vector<int>& vec){
    // base case 
    int size = vec.size();
    if(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 i=mid;i<size;i++){
        sub_vec2.push_back(vec[i]);
    }
    // 递归链条 
    mergeSort(sub_vec1);
    mergeSort(sub_vec2);

    vec.clear();
    mergeTwoSortedVec(sub_vec1,sub_vec2,vec); // 合并 
}

void myPrint(vector<int> vec){
    for(auto it = vec.cbegin();it != vec.cend();it++){
        cout <<*it << " ";
    }
    cout << endl;
}

int main(){

    vector<int> vec = {5,-7,9,1,1};
    myPrint(vec);
    mergeSort(vec);
    myPrint(vec);



    return 0;
}
使用分治对一个非有序数组进行排序

 

 

例4:逆序数(LeetCode No.315)

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元素的数量。

输入:nums = [5,2,6,1]
输出:[2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素

 

 

思路及代码

使用分治来解决,

思考:

 

 

算法思路:

 

 

插入j对应的元素时,就是直接j 对应的值,

 

 

 

 

count 的顺序问题:

 

 

 

 

 

 

 

 

#include <iostream>
#include <vector>

using namespace std;

void mergeTwoSortedVec(vector<pair<int,int>>& vec1,vector<pair<int,int>>& vec2,vector<pair<int,int>>& res,vector<int>& count ){

    int i = 0;
    int j = 0;
    int size1 = vec1.size();
    int size2 = vec2.size();
    while(i<size1 && j<size2){
        if(vec1[i].first <= vec2[j].first){ 
            count[vec1[i].second] += j;
            res.push_back(vec1[i]);
            i++;
        }else{
            res.push_back(vec2[j]);
            j++;
        }
    }
    // 将 vec1 和 vec2 剩余的元素 push 进 res
    for(;i<size1;i++){
        count[vec1[i].second] += j;
        res.push_back(vec1[i]);
    }
    
    for(;j<size2;j++){
        res.push_back(vec2[j]);
    }
}

void mergeSort(vector<pair<int,int>>& vec,vector<int>& count){
    // base case 
    int size = vec.size();
    if(size <= 1){ // 如果问题足够小 直接求解
        return;
    }
    int mid =  vec.size()/2; 
    vector<pair<int,int>> sub_vec1; // 将原问题拆分为 两个 规模相同的问题
    vector<pair<int,int>> sub_vec2;
    for(int i=0;i<mid;i++){
        sub_vec1.push_back(vec[i]);
    }
    for(int i=mid;i<size;i++){
        sub_vec2.push_back(vec[i]);
    }
    // 递归链条 
    mergeSort(sub_vec1,count);
    mergeSort(sub_vec2,count);

    vec.clear();
    mergeTwoSortedVec(sub_vec1,sub_vec2,vec,count); // 合并 
}

void myPrint(vector<int> vec){
    for(auto it = vec.cbegin();it != vec.cend();it++){
        cout <<*it << " ";
    }
    cout << endl;
}

vector<int> countSmaller(vector<int>& nums) {
    vector<pair<int,int>> vec; // 将 nums[i] 和 i 绑定到一起 放入vec
    vector<int> count;
    for(int i=0;i<(int)nums.size();i++){
        vec.push_back(make_pair(nums[i],i));
        count.push_back(0); // 初始为0  
    }
    mergeSort(vec,count); // 使用vec中pair 的第一个数进行排序 
    return count;
}

int main(){

    vector<int> data = {5,-7,9,1,1};
    countSmaller(data);


    return 0;
}
View Code
class Solution {
private:
void mergeSort(vector<pair<int,int>>& vec,vector<int>& count){
    // base case 
    int size = vec.size();
    if(size <= 1){ // 如果问题足够小 直接求解
        return;
    }
    int mid =  vec.size()/2; 
    vector<pair<int,int>> sub_vec1; // 将原问题拆分为 两个 规模相同的问题
    vector<pair<int,int>> sub_vec2;
    for(int i=0;i<mid;i++){
        sub_vec1.push_back(vec[i]);
    }
    for(int i=mid;i<size;i++){
        sub_vec2.push_back(vec[i]);
    }
    // 递归链条 
    mergeSort(sub_vec1,count);
    mergeSort(sub_vec2,count);

    vec.clear();
    mergeTwoSortedVec(sub_vec1,sub_vec2,vec,count); // 合并 
}

void mergeTwoSortedVec(vector<pair<int,int>>& vec1,vector<pair<int,int>>& vec2,vector<pair<int,int>>& res,vector<int>& count ){

    int i = 0;
    int j = 0;
    int size1 = vec1.size();
    int size2 = vec2.size();
    while(i<size1 && j<size2){
        if(vec1[i].first <= vec2[j].first){ 
            count[vec1[i].second] += j;
            res.push_back(vec1[i]);
            i++;
        }else{
            res.push_back(vec2[j]);
            j++;
        }
    }
    // 将 vec1 和 vec2 剩余的元素 push 进 res
    for(;i<size1;i++){
        count[vec1[i].second] += j;
        res.push_back(vec1[i]);
    }
    
    for(;j<size2;j++){
        res.push_back(vec2[j]);
    }
}



public:
vector<int> countSmaller(vector<int>& nums) {
    vector<pair<int,int>> vec; // 将 nums[i] 和 i 绑定到一起 放入vec
    vector<int> count;
    for(int i=0;i<(int)nums.size();i++){
        vec.push_back(make_pair(nums[i],i));
        count.push_back(0); // 初始为0  
    }
    mergeSort(vec,count); // 使用vec中pair 的第一个数进行排序 
    return count;
}











};
View Code

 

posted @ 2020-09-12 12:29  Zcb0812  阅读(148)  评论(0编辑  收藏  举报