五月集训(第03天)——排序

排序

1. 977. 有序数组的平方

    思路:
        对每个数平方后排序即可

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        vector<int> ret;
        for (int i = 0; i < n; i++) ret.push_back(nums[i] * nums[i]);
        sort(ret.begin(), ret.end());
        return ret;
    }
};

2. 268. 丢失的数字

    思路:
        排序后找到第一个下标与值不相等的数,下标即为丢失的数组

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        for (int i = 0; i < n; i++) {
            if (nums[i] != i) return i;
        }
        return n;
    }
};

3. 1877. 数组中最大数对和的最小值

    思路:
        要对数组两两组合为数对,取所有数对和的最大值,让该最大值对最小。让最大值与最小值,次大值与次小值配对,否则肯定会有更大的值。对数组排序,两端向内组成数对即可。

class Solution {
public:
    int minPairSum(vector<int>& nums) {
        int n = nums.size();
        int maxn = -1;
        sort(nums.begin(), nums.end());
        int len = n / 2;
        for (int i = 0; i < len; i++)
            maxn = max(maxn, nums[i] + nums[n - 1 -i]);
        return maxn;
    }
};

4. 多个数组求交集

    题意:
        给出一个排列顺序,按要求读取能够让结果按顺序显示。


    思路1:
        逆向思维:从顺序排列后的数组出发,倒推出输入的排列顺序。
操作要求显示一张,将一张放入底部。所以从最后一张出发,每次从显示的数组中取出最晚显示的数放入还原队列中,队尾是被将要加入还原队列的数放到最后的,于是将队尾放到队首再将要放入的数入队(还原过程)。
逆序
正向时依次显示[2,3,5,7,11,13,17],那么我们反过来构造时,依次选择[17,13,11,7,5,2,3]

  1. 选择 17。插入17,牌组现在是 [17]。
  2. 选择 13。先将 17 移到顶部,然后插入13。牌组现在是 [13,17]。
  3. 选择 11。先将 17 移到顶部,然后插入11。牌组现在是 [11,17,13]。
  4. 选择 7。先将 13 移到顶部,然后插入7。牌组现在是 [7,13,11,17]。
  5. 选择 5。先将 17 移到顶部,然后插入5。牌组现在是 [5,17,7,13,11]。
  6. 选择 3。先将 11 移到顶部,然后插入3。牌组现在是 [3,11,5,17,7,13]。
  7. 选择 2。先将 13 移到顶部,然后插入3。牌组现在是 [2,13,3,11,5,17,7]。


            解法一(C++)
class Solution {
public:
    vector<int> deckRevealedIncreasing(vector<int>& deck) {
        vector<int> ans;
        int len = deck.size();
        sort(deck.begin(), deck.end());
        ans.push_back(deck[len - 1]);   // 首先放入最后一个元素
        for (int i = len - 2; i >= 0; i--) {
            ans.push_back(ans.front()); // 将第一个元素加入最后
            ans.erase(ans.begin());
            ans.push_back(deck[i]);
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

        解法二(C):由于向队首调整不好实现,于是将该过程反过来,向队尾调整,最后将得到的结果逆序输出即可

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int cmp(const int *a, const int *b) {return *a - *b;}

int* deckRevealedIncreasing(int* deck, int deckSize, int* returnSize){
    int *Queue = (int *)malloc(sizeof(int) * deckSize * 2);
    int l = 0, r = 1, i = deckSize - 2;
    *returnSize = deckSize;
    qsort(deck, deckSize, sizeof(int), cmp);
    Queue[0] = deck[deckSize - 1];    // 将deck[]中的数逆序放入
    while (r - l < deckSize) {
        Queue[r++] = Queue[l++];    // 将队首放入队尾,队首出队
        Queue[r++] = deck[i--];   // 将下一个数放入
    }
    int index = 0;
    for (int i = r - 1; i >= l; i--) deck[index++] = Queue[i];
    return deck;
}

    思路2:
        正向出发,每次都是显示一个数,将下一个数放入队尾。那么还原过程只需要将显示结果逐个放回即可。创建一个空数组,放入第一个要显示的数,向后寻找一个空格(即为被放入队尾的数),跳过,找到第二个空格放入下一显示的数,如此反复。
下面为演示过程, % 为找到的第一个空格被跳过



/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int cmp(const int *a, const int *b) {return *a - *b;}

int* deckRevealedIncreasing(int* deck, int deckSize, int* returnSize){
    int *ret = (int *)malloc(sizeof(int) * deckSize);
    *returnSize = deckSize;
    for (int i = 0; i < deckSize; i++) ret[i] = 0;
    qsort(deck, deckSize, sizeof(int), cmp);
    ret[0] = deck[0];
    int index = 0;
    for (int i = 1; i < deckSize; i++) {
        while (ret[index] != 0) {   // 找到第一空位(跳过该空位放入下一个空位)
            index = (index + 1) % deckSize;
        }
        index = (index + 1) % deckSize; // 从空位后面开始找下一个空位
        while (ret[index] != 0) {   // 找到第二个空位,放入当前值
            index = (index + 1) % deckSize;
        }
        ret[index] = deck[i];
    }
    return ret;
}
posted @ 2022-05-03 11:59  番茄元  阅读(5)  评论(0)    收藏  举报