五月集训(第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]
- 选择 17。插入17,牌组现在是 [17]。
- 选择 13。先将 17 移到顶部,然后插入13。牌组现在是 [13,17]。
- 选择 11。先将 17 移到顶部,然后插入11。牌组现在是 [11,17,13]。
- 选择 7。先将 13 移到顶部,然后插入7。牌组现在是 [7,13,11,17]。
- 选择 5。先将 17 移到顶部,然后插入5。牌组现在是 [5,17,7,13,11]。
- 选择 3。先将 11 移到顶部,然后插入3。牌组现在是 [3,11,5,17,7,13]。
- 选择 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;
}
东方欲晓,莫道君行早。