题意
交换无重复元素的数组中第m大和第n大的数字,返回交换后的新数组
方法
for套for
控制上限每次找小于上限的最大值,这样找了n次,就是第n大的值
我们把最大值最小值用long long来表示保证超过int的范围
以7 3 2 8 4 为例, 若n=4
| 轮次 | pos | val | n | 
|---|---|---|---|
| 1 | -1 | 0x3f3f3f3f3f | 4 | 
| 2 | 3 | 8 | 3 | 
| 3 | 0 | 7 | 2 | 
| 4 | 4 | 4 | 1 | 
| 5 | 1 | 3 | 0 | 
所以第4大的是3
代码
class Solution {
public:
    int findMaxN(vector<int> & a,int n){
        int pos = -1;
        long long val = 0x3f3f3f3f3f; // 保证大于int
        // 每次寻找小于val的最大的,以此寻找n次 就是第n大的
        while(n--){
            long long v = -0x3f3f3f3f3f; // 保证小于int
            long long idx = 0;
            for(int i = 0;i<a.size();i++){
                if(a[i] >= val)continue; // 忽略大于等于的部分
                if(a[i] > v){
                    v=a[i];
                    idx = i;
                }
            }
            // 更新该轮搜索的结果
            pos = idx;
            val = v;
        }
        return pos;
    }
    /**
     * 
     * @param a int整型vector 原始数组a
     * @param n int整型 第n大
     * @param m int整型 第m大
     * @return int整型vector
     */
    vector<int> sovle(vector<int>& a, int n, int m) {
        vector<int> ans = a;
        swap(ans[findMaxN(a,n)],ans[findMaxN(a,m)]);
        return ans;
    }
};
 复杂度分析
时间复杂度: 我们遍历n次数组寻找第n大的数,时间复杂度为O(n⋅a.size()),交换元素是常数时间,复制数组O(a.size()),所以总时间复杂度为(O((n+m)⋅a.size())) ,好在题目的数据范围的确很小能够AC
空间复杂度: 我们储存内容只有一个结果数组,和传入的a是一致的,所以空间复杂度为O(n)
制作pair并排序
我们的任务,找到那两个数是第n大和第m大的,找到这两个数的位置并交换。
C++默认的sort从小到大,我们把值取负并和下标做成一个pair,让c++自己去排序,这样我们就能让原始值从大到小,并且知道它的下标了
所以步骤变成
- 制作
pair<-值,下标>的vector sort排序swap对应未知的值- 返回 交换后的
vector 
以7 3 2 8 4 为例
| - | 7 | 3 | 2 | 4 | 8 | 
|---|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 | 
| pair | {-7,0} | {-3,1} | {-2,2} | {-4,3} | {-8,4} | 
从小到大排序
| 下标 | 0 | 1 | 2 | 3 | 4 | 
|---|---|---|---|---|---|
| pair | {-8,4} | {-7,0} | {-4,3} | {-3,1} | {-2,2} | 
这样,我们对于原始值来说是从大到小8,7,4,3,2, 对于要去第n大的,去对应n−1下标就能拿到原始的下标。从而可以对a数组进行交换
代码
class Solution {
public:
    /**
     * 
     * @param a int整型vector 原始数组a
     * @param n int整型 第n大
     * @param m int整型 第m大
     * @return int整型vector
     */
    vector<int> sovle(vector<int>& a, int n, int m) {
        vector<pair<int,int> > b;
        for(int i = 0;i<a.size();i++){
            b.push_back({-a[i],i});
        } 
        sort(b.begin(),b.end());
        vector<int> ans = a;
        swap(ans[b[n-1].second],ans[b[m-1].second]);
        return ans;
    }
};
 复杂度分析
时间复杂度: 建立 排序vector和结果vector,O(n),排序过程期望是O(nlog(n)),总时间复杂度O(n⋅log(n))
空间复杂度: 我们储存内容主要是两个vector,内容数量和传入的a是一致的,所以空间复杂度为O(n)
知识点
- 大多数情况你需要建立一个不是很极限大小的数组时会耗费O(n)时间,对他排序是O(nlog(n)), 一般来说没有卡常数的题目只要O(n)能过,一般O(nlog(n))也是同样能过的,在一些更复杂的题目里,甚至题目帮你都把续排好了。
 - 使用
pair和tuple能省去一些结构体的实现和构建,并能使用c++默认提供的排序,二分查找等功能,而如果自己的结构体你可能需要提供比较函数的实现,在一些支持C++更高版本的语法的地方,使用pair,tuple能写出十分简洁的代码。比如从大到小排序,你也可以提供比较函数,或者用C++提供的greater<>(), 但通过加个符号,可以简洁的实现顺序的颠倒。 

京公网安备 11010502036488号