数组-算法小结

数组

二分法
快慢指针(移除元素)
双指针(有序数组的平方)
滑动窗口( 长度最小的子数组)
区间和
螺旋矩阵II (边界问题)

二分法

思想 : 不断把区间二分为一,逼进目标值
使用前提 :有序数组
关于二分mid溢出:

  • mid={l+r)/2时 如果l+r大于INT_MAX (int整型的上限)会溢出
  • 所以写成mid=l+(r-l)/2 / mid=l+(r-l)>>1
    注意区间:
    左闭右闭区间 [left, right]
    左闭右开区间 [left, right)
    704. 二分查找 - 力扣(LeetCode)
 int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size(); 
        while (left < right) { 
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target) {
                right = middle; 
            } else if (nums[middle] < target) {
                left = middle + 1; 
            } else { 
                return middle; 
            }
        }
        return -1;
    }

快慢指针

快指针在旧数组中找非目标值,然后赋值给慢指针指向的新数组
27. 移除元素 - 力扣(LeetCode)
vector.size()空数组返回0,再减去一会溢出,变成一个很大的负数

   int removeElement(vector<int>& nums, int val) {
        int j=0;
       for(int i=0;i<nums.size();i++){
            if(nums[i]!=val){
               nums[ j++]= nums[i];
            }
       }       
         return j;
    }

双指针

使用前提 :有序数组
977. 有序数组的平方 - 力扣(LeetCode)

 vector<int> sortedSquares(vector<int>& A) {
        int k = A.size() - 1;
        vector<int> result(A.size(), 0);
        for (int i = 0, j = A.size() - 1; i <= j;) { 
        // 注意这里要i <= j,因为最后要处理两个元素
            if (A[i] * A[i] < A[j] * A[j])  {
                result[k--] = A[j] * A[j];
                j--;
            }
            else {
                result[k--] = A[i] * A[i];
                i++;
            }
        }
        return result;
    }

区间和(前缀和)

预先计算并存储数组前i个元素的和
[___这样在查询区间和的时候只需要做一次减法操作,时间复杂度可以降到O(1) _ ]

原数组 → [1, 3, 2, 5]
前缀和 → [0, 1, 4, 6, 11]
## 
问:求[1,3]号元素和( 3+2+5 )?
答:prefix[4] - prefix[1] = 11 - 1 = 10
int main()
{
    int n, a, b;
    cin >> n;
    vector<int>nums(n, 0);
    vector<int>sum_nums(n, 0);
    for (int i = 0; i < n; i++)
    {
        cin >> nums[i];
        if (i > 0)
            sum_nums[i] = nums[i] + sum_nums[i - 1];
        else if (i == 0) sum_nums[i] = nums[i];

    }

    while (cin >> a >> b) {
        int sum;
        if (a == 0) sum = sum_nums[b];
        else sum = sum_nums[b] - sum_nums[a - 1];
        cout << sum << endl;

    }

}

滑动窗口

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?
    窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。
    窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引
    209. 长度最小的子数组 - 力扣(LeetCode)
    int minSubArrayLen(int target, vector<int>& nums) {
    int i=0;
    int sum=0;
    int length=0;
    int result=INT32_MAX;
    for(int j=0;j<nums.size();j++)
    {
       sum+=nums[j];
       while(sum>=target){
       length=(j-i+1);
       result=length<result?length:result;
       sum-=nums[i++];
       }
    }
     return result==INT32_MAX?0:result;
    }

螺旋矩阵II

阴间细节
左闭右开原则
每次拐角,即每个for循环不处理最后一个元素,避免重复填充
奇数的特殊关怀
当n为奇数时,最后会剩下一个中心点
偏移
每完成一层,offset++使得下一层的遍历范围减少:
59. 螺旋矩阵 II - 力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值