代码随想录算法训练营第二天打卡

1.有序数组的平方

Leetcode题目链接

这道题有两种方法,一种是我自己想的,另外一种是从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;
    }
}

今毕

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值