算法刷题之数组

1.二分查找  O(logn)

模板题 - 力扣(LeetCode)

算法前提:有序数组

算法核心:理解对查找区间的定义(正确答案所在区间),在循环中根据区间定义做边界处理

class Solution {
public:
    int search(vector<int>& nums, int target) {
        // 定义target在[left, right]区间
        int min = 0, max = nums.size() - 1, mid;
        // 闭区间内min == max合法,需要取等号
        while(min <= max){  
            // 防止大数溢出
            mid = min + (max - min) / 2;
            if(nums[mid] > target){
                max = mid - 1;
            }
            else if(nums[mid] < target){
                min = mid + 1;
            }
            else return mid;
        }
        return -1;
    }
};

 拓展题:

35. 搜索插入位置 - 力扣(LeetCode)(注意对插入情况的分析讨论)

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

69. x 的平方根 - 力扣(LeetCode)

367. 有效的完全平方数 - 力扣(LeetCode)

2.排序  O(nlogn)

1.快速排序

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }

    // 分治
    quick_sort(q, l, j);
    quick_sort(q, j + 1, r);
}

2.归并排序

void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int mid = l + r >> 1;

    merge_sort(q, l, mid), merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];
    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}

3.双指针  O(n)

27. 移除元素 - 力扣(LeetCode)

int removeElement(vector<int>& nums, int val) {
    // 慢指针记录个数
    int slowIndex = 0;
    // 快指针扫描数组
    for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
        // 把符合要求的数前移(所有符合要求的数都在慢指针后面,不会产生覆盖问题)
        if (val != nums[fastIndex]) {
            nums[slowIndex++] = nums[fastIndex];
        }
    }
    return slowIndex;
}

4.滑动窗口  O(n)

209. 长度最小的子数组 - 力扣(LeetCode)

int minSubArrayLen(int target, vector<int>& nums) {
    // 滑动窗口
    // j依次移动分别表示以0 - nums.size() - 1为右端点的长度最小的数组(对子数组的分类!)
    int i = 0, j = 0, sum = 0, res = INT32_MAX;
    for(; j < nums.size(); j ++){
        sum += nums[j];
        if(sum < target) continue;
        else{
            while(i < j && sum - nums[i] >= target){
                sum -= nums[i ++];
            }
            res = min(res, j - i + 1);
        }
     }
     if(res == INT32_MAX) return 0;
     else return res;
}

拓展题:

904. 水果成篮 - 力扣(LeetCode)

5.模拟过程

59. 螺旋矩阵 II - 力扣(LeetCode)

vector<vector<int>> generateMatrix(int n) {
    int x = 0, y = 0;
    // 模拟顺时针前进方向
    int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0}, d = 0;
    vector<vector<int>> res(n, vector<int>(n, -1));
    for(int i = 0; i < n * n; i ++ ){
        res[x][y] = i + 1;

        if(d == 0 && (y + 1 >= n || res[x][y + 1] != -1)) d = 1;
        else if(d == 1 && (x + 1 >= n || res[x + 1][y] != -1)) d = 2;
        else if(d == 2 && (y - 1 < 0 || res[x][y - 1] != -1)) d = 3;
        else if(d == 3 && (x - 1 < 0 || res[x - 1][y] != -1)) d = 0;
        
        x += dx[d];
        y += dy[d];
    }
    return res;
}

 6.前缀和与差分

本质为数列题,由通项公式求前n项和、由前n项和求通项公式

58. 区间和(第九期模拟笔试) (kamacoder.com)

int n;
cin >> n;
int a[n + 1], s[n + 1];
for(int i = 1; i <= n; i ++ ){
    cin >> a[i];
    s[i] = a[i] + s[i - 1];
}
int x, y;
while(cin >> x >> y){
    cout << s[y + 1] - s[x] << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值