1.有序数组的平方
这道题有两种方法,一种是我自己想的,另外一种是从Carl那儿学到的。
方法一:将数组的负数部分先取绝对值,然后排序。这样子平方后的数组也一定是按照升序的顺序来的。但是,这个方法的实现略显复杂,而且时间复杂度较高,这里演示。
方法二:Carl的方法,使用两个指针分别指向原数组的头和尾,然后将数组的头和尾依次平方并比较。代码如下:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size());
for (int i = 0, j = nums.size() - 1, k = nums.size() - 1; i <= j;){
if (nums[i] * nums[i] >= nums[j] * nums[j]){
result[k] = nums[i] * nums[i];
k--;
i++;
} else {
result[k] = nums[j] * nums[j];
k--;
j--;
}
}
return result;
}
};
可以在本地IDE完整运行的代码如下:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size());
for (int i = 0, j = nums.size() - 1, k = nums.size() - 1; i <= j;){
if (nums[i] * nums[i] >= nums[j] * nums[j]){
result[k] = nums[i] * nums[i];
k--;
i++;
} else {
result[k] = nums[j] * nums[j];
k--;
j--;
}
}
return result;
}
};
int main()
{
Solution sol;
vector<int> nums;
nums.push_back(-4);
nums.push_back(-1);
nums.push_back(0);
nums.push_back(3);
nums.push_back(10);
vector<int> arr = sol.sortedSquares(nums);
for (int i = 0; i < arr.size(); i++){
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
2.长度最小的子数组
本地的关键就是要了解滑动窗口。其中,滑动窗口的本质其实就是双指针。并且,要注意实时更新最小子数组,才能得到最终答案。
与此同时,我自己也想出来了一种解法:先将数组整体排序,然后从大到小累加,判断是否存在最小子数组满足条件。若满足,则输出结果,如不满足,则返回0.
我自己的方法代码如下:
class Solution { //我自己的解法,整体思想就是先给数组排序,然后再累加,查看是否满足要求
public:
int minSubArrayLen(int target, vector<int>& nums) {
sort(nums.begin(), nums.end());
int temp = 0;
int i, j;
for (i = nums.size() - 1, j = 0; i >= 0;){
if (temp < target){
temp += nums[i];
i--;
j++;
}
}
if (temp >= target){
return j;
} else {
return 0;
}
}
};
滑动窗口法代码如下:
class Solution { //滑动窗口解法,本质上是双指针
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0; // 滑动窗口数值之和
int i = 0; // 滑动窗口起始位置
int subLength = 0; // 滑动窗口的长度
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
可在本地IDE运行的完整代码如下:
#include <iostream>
#include <vector>
using namespace std;
// class Solution { //我自己的解法,整体思想就是先给数组排序,然后再累加,查看是否满足要求
// public:
// int minSubArrayLen(int target, vector<int>& nums) {
// sort(nums.begin(), nums.end());
// int temp = 0;
// int i, j;
// for (i = nums.size() - 1, j = 0; i >= 0;){
// if (temp < target){
// temp += nums[i];
// i--;
// j++;
// }
// }
// if (temp >= target){
// return j;
// } else {
// return 0;
// }
// }
// };
class Solution { //滑动窗口解法,本质上是双指针
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0; // 滑动窗口数值之和
int i = 0; // 滑动窗口起始位置
int subLength = 0; // 滑动窗口的长度
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
int main(int argc, char** argv) {
vector<int> nums;
nums.push_back(1);
nums.push_back(1);
nums.push_back(1);
nums.push_back(1);
nums.push_back(1);
nums.push_back(1);
nums.push_back(1);
nums.push_back(1);
Solution sol;
int target = 11;
int num = sol.minSubArrayLen(target, nums);
cout << num << endl;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++){
cout << nums[i] << " ";
}
cout << endl;
return 0;
}
3.螺旋矩阵
这道题需要分四条边依次遍历并赋值,遵循左闭右开的原则,并且需要处理n为奇数的情况。由外向内一次遍历并赋值,代码如下:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<vector<int> > generateMatrix(int n) { //循环遍历每一条边,每一条边遵循左闭右开原则
vector<vector<int> > matrix(n, vector<int>(n, 0)); //二维数组必须初始化
int startX = 0, startY = 0;
int count = 1, offset = 1;
int i, j;
int loop = n / 2;
while (loop > 0) {
for (i = startX, j = startY; j < n - offset; j++) {
matrix[i][j] = count;
count++;
}
for (; i < n - offset; i++) {
matrix[i][j] = count;
count++;
}
for (; j > startY; j--) {
matrix[i][j] = count;
count++;
}
for (; i > startX; i--) {
matrix[i][j] = count;
count++;
}
loop--;
startX++;
startY++;
offset++;
}
if (n % 2 == 1) {
int x = n / 2;
int y = n / 2;
matrix[x][y] = count;
}
return matrix;
}
};
int main() {
int n = 5;
Solution sol;
vector<vector<int> > matrix = sol.generateMatrix(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
可以在本地IDE运行的完整代码如下:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<vector<int> > generateMatrix(int n) { //循环遍历每一条边,每一条边遵循左开右闭原则
vector<vector<int> > matrix(n, vector<int>(n, 0)); //二维数组必须初始化
int startX = 0, startY = 0;
int count = 1, offset = 1;
int i, j;
int loop = n / 2;
while (loop > 0) {
for (i = startX, j = startY; j < n - offset; j++) {
matrix[i][j] = count;
count++;
}
for (; i < n - offset; i++) {
matrix[i][j] = count;
count++;
}
for (; j > startY; j--) {
matrix[i][j] = count;
count++;
}
for (; i > startX; i--) {
matrix[i][j] = count;
count++;
}
loop--;
startX++;
startY++;
offset++;
}
if (n % 2 == 1) {
int x = n / 2;
int y = n / 2;
matrix[x][y] = count;
}
return matrix;
}
};
int main() {
int n = 5;
Solution sol;
vector<vector<int> > matrix = sol.generateMatrix(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
今毕