第一章 数组(leetcode 704,27,997,209,59)

数组简介

  • 现代C++程序应该使用标准库容器,而不是更原始的数据结构,如内置数组。事实上,std::array有和内置数组几乎一样的性能,以及更丰富的特性。如支持拷贝和赋值,且拥有众多成员函数。
  • 通常,使用std::vector是最好的选择,除非你有更好的理由选择其他容器。std::vector可变大小数组,支持快速随机访问,在尾部之外的位置插入或删除元素可能较慢。

704.二分查找

题目链接

  • 对于有序序列,使用二分查找
  • lohi取区间端点的开闭清况,取决于你是否需要使用区间端点的元素,需要为闭,不需要为开。
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int lo = 0;
        int hi = nums.size() - 1; // 闭区间,需要该位置的元素
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (nums[mid] < target) {
                lo = mid + 1;
            } else if (nums[mid] > target) {
                hi = mid - 1; //需要该位置的元素
            } else {
                return mid;
            }
        }
        return -1;
    }
};

27.移除元素

题目链接

  • 问题在与,如何一次遍历就移除所以元素。用两根指针,一根指针完成遍历,遍历过程中跳过移除的元素,赋值给另一根指针。
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        int sl = 0;
        int qu = 0;
        while (qu < size) {
            if (nums[qu] != val) { // 跳过该移除的数
                nums[sl] = nums[qu];
                ++sl;
            }
            ++qu;
        }
        return sl;
    }
};

997.有序数组的平方

题目链接

  • 注意到,对于有序数组,最大的平方数一定位于两端,数组两端各用一个指针遍历。
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> newNums(nums.size());
        int le = 0;
        int ri = nums.size() - 1;
        for (int i = nums.size() - 1; i >= 0; --i) {
            int leNum = nums[le] * nums[le];
            int riNum = nums[ri] * nums[ri];
            newNums[i] = (leNum >= riNum) ? (le++, leNum) : (ri--, riNum);
        }
        return newNums;
    }
};

209.长度最小的字数组

题目链接

  • 如何减少遍历次数。使用两个指针组成滑动窗口,两个指针均只能前进不能后退,仅遍历一遍即可。
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int le = 0;
        int ri = 0;
        int minLength = INT32_MAX;
        int size = nums.size();
        int sum = 0;

        while (ri < size) {
            sum += nums[ri];
            while (sum >= target) {
                minLength = minLength <= ri - le + 1 ? minLength : ri - le + 1;
                sum -= nums[le++];
            }
            ++ri;
        }

        return minLength == INT32_MAX ? 0 : minLength;
    }
};

59.螺旋矩阵II

题目链接

  • 使用for循环模拟螺旋操作,每一条边操作时,要恪守区间选择原则。
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n, std::vector<int>(n, 0));
        int loopMaxNum = n / 2;
        int loopNum = 0;
        int num = 1;
        while (loopNum < loopMaxNum) {
            for (int i = loopNum; i < n - 1 - loopNum; ++i)
                result[loopNum][i] = num++;
            for (int j = loopNum; j < n - 1 - loopNum; ++j)
                result[j][n - 1 - loopNum] = num++;
            for (int k = n - 1 - loopNum; k > loopNum; --k)
                result[n - 1 - loopNum][k] = num++;
            for (int l = n - 1 - loopNum; l > loopNum; --l)
                result[l][loopNum] = num++;

            loopNum++;
        }
        if (n % 2 == 1)
            result[n / 2][n / 2] = num;
        return result;
    }
};

区间和

题目链接

  • 使用前缀和,来解决大量查询时,时间消耗的问题
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() {
    int n, a, b;
    cin >> n;
    vector<int> preSum(n, 0);
    int sum = 0;
    vector<int> num(n, 0);
    for (int i = 0; i < n; ++i) {
        cin >> num[i];
        sum += num[i];
        preSum[i] = sum;
    }
    while (cin >> a >> b) {
        int result;
        if (a == 0)
            result = preSum[b];
        else
            result = preSum[b] - preSum[a - 1];

        cout << result << endl;
    }
    return 0;
}

开发商购买土地

题目链接

  • 统计列前缀和行前缀
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() {
    int n, m;
    cin >> n >> m;
    int sum = 0;
    vector<vector<int>> vec(n, vector<int>(m, 0));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> vec[i][j];
            sum += vec[i][j];
        }
    }
    // 统计横向
    vector<int> horizontal(n, 0);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            horizontal[i] += vec[i][j];
        }
    }
    // 统计纵向
    vector<int> vertical(m, 0);
    for (int j = 0; j < m; ++j) {
        for (int i = 0; i < n; ++i) {
            vertical[j] += vec[i][j];
        }
    }
    int result = INT_MAX;
    int horizontalCut = 0;
    for (int i = 0; i < n; ++i) {
        horizontalCut += horizontal[i];
        result = min(result, abs(sum - horizontalCut - horizontalCut));
    }
    int verticalCut = 0;
    for (int j = 0; j < m; ++j) {
        verticalCut += vertical[j];
        result = min(result, abs(sum - verticalCut - verticalCut));
    }
    cout << result << endl;
}

待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值