LeetCode_数组

本文详细介绍了力扣上的数组和二分查找相关问题,包括二分查找算法的递归和循环实现,以及在移除元素、有序数组的平方、最短连续子数组和螺旋矩阵等场景的应用。此外,还讨论了数组操作如双指针法,以及如何解决三数之和、四数之和的问题。文章总结了数组篇的关键技术和vector的使用技巧。
摘要由CSDN通过智能技术生成

力扣刷题(代码随想录顺序)

数组

二分查找


704. 二分查找【简单题】
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

算法思路:通过两个指针,左边为称为L(left) 右边为R(right),
(L+R)/2=M
分为三种情况:
如果M的值等于target 那么返回M
如果M的值大于target 那么就说明要找的值在M指针的左边,此时将R赋值为M,继续重复
如果M的值小于target 那么就说明要找的值在M指针的右边,此时将L赋值为M,重复
那么程序出口是什么呢?假设在最后还没找到 那么我们可以往回退两个步骤
LMR-> L(M)R(此时LM是同一个位置) -> (LMR)(此时LMR都在同一个位置)
代码实现:
递归法实现
循环实现
下面展示一些 内联代码片

#include <vector>
#include<iostream>
using namespace std;
class Solution {
public:
    int search(vector<int>& nums, int target) {
        return sea(0,nums.size()-1,nums,target);
    }
    int sea(int l,int r,vector<int>& nums, int target){
        int m = (l+r)>>1;
        if (l==r) return -l;
        else if (nums[m]==target) return m;
        else if(nums[m]>target) return sea(l,m, nums,target);
        else if(nums[m]<target) return sea(m,r,nums,target);
    }
};
class Solution2{
public:
    int search(vector<int> &nums,int target){
        int r = nums.size()-1;
        int l = 0;
        int m = (l+r)>>1;
        while(true){
            if(l==r){
                m = -1;
                break;
            }
            else if (nums[m]>target) r = m;
            else if (nums[m]<target) l = m;
            else if (nums[m]==target) break;
            m = (l+r)>>1;
        }
        return m;
    }

};

移除元素

思路,总体来说就是将后面的元素覆盖前面的元素
实现方法有两个
方法一:暴力循环这没什么好说的学过C语言就应该回了
方法二:双指针法
注:这里使用了代码随想录的一个图,侵权删!
看图就懂了
代码思路:
情况一:fast =low -> fast++ low++
情况二:fast != low ->
情况一:
nums[fast]!=val
nums[low] = nums[fast]
fast ++ low ++
情况二:
nums[fast] ==val
fast++
len–

class Solution {
public:
    int search(vector<int>& nums, int target) {
        return sea(0,nums.size()-1,nums,target);
    }
    int sea(int l,int r,vector<int>& nums, int target){
        int m = (l+r)>>1;
        if (l==r) return -l;
        else if (nums[m]==target) return m;
        else if(nums[m]>target) return sea(l,m, nums,target);
        else if(nums[m]<target) return sea(m,r,nums,target);
    }
};
class Solution2{
public:
    int search(vector<int> &nums,int target){
        int r = nums.size()-1;
        int l = 0;
        int m = (l+r)>>1;
        while(true){
            if(l==r){
                m = -1;
                break;
            }
            else if (nums[m]>target) r = m;
            else if (nums[m]<target) l = m;
            else if (nums[m]==target) break;
            m = (l+r)>>1;
        }
        return m;
    }

977.有序数组的平方

题目说明
// 977. 有序数组的平方
// 给你一个按 非递减顺序 排序的整数数组 nums,返回 每
// 个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

// 示例 1:

// 输入:nums = [-4,-1,0,3,10]
// 输出:[0,1,9,16,100]
// 解释:平方后,数组变为 [16,1,0,9,100]
// 排序后,数组变为 [0,1,9,16,100]
解题思路
先排序,然后一个指针指向尾指针,一个头指针,谁的平方大谁动
图

class Solution{
public:
    vector<int> sortedSquares(vector<int>& nums){
        vector<int> result = vector<int>(nums.size(),0);
        int k = nums.size()-1;
        for(int i=0,j=nums.size()-1;i<=j;){
            if (nums[i]*nums[i]<=nums[j]*nums[j]){
                result[k--] = nums[j]*nums[j];
                j--;
            }        

            else{
                result[k--] = nums[i]*nums[i];
                i++;
            }
        }
        return result;
    }
};

209.长度最小的子数组

题目说明
/*
209.长度最小的子数组
题目链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum/

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例:

输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
*/
同样用双指针法,一个头指针一个尾指针,在头尾指针之和大于s时,尾向前移动,小于s时,头向前移动,当相加起来等于s时,不断向前即可。

螺旋矩阵Ⅱ

题目说明:
我直接举例把
01 02 03 04
12 13 14 05
11 16 15 06
10 09 08 07
这道题我并不认为难并且思路和代码随想录的不一样,我是用了四个挡板,也就是上下左右具体看代码就很容易懂

class Solution {
public:
   vector<vector<int>> generateMatrix(int n) {
       int left = 0;
       int right = n-1;
       int up = 0;
       int down = n-1;
       vector<vector<int>>  res(n, vector<int>(n, 1));//知识点一个
       int i =0;
       int j = 0;
       int count = 1;
       
       while(true){
           //向左跑
           while( j<right )
               res[i][++j]=++count;
           up+=1;//上挡板下降一个
           
           //向下跑

           while(i<down)
               res[++i][j] = ++count;
           right-=1;

           while(j>left)
               res[i][--j] = ++count;
           down--;//下挡板上升一个

           while(i>up)
               res[--i][j]=++count;
           left++;
           
           if(count>=n*n)
               break;
       }
       return res;
   }
};

1二数之和

没什么好说的 跳过一下

2三数之和

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:[ [-1, 0, 1], [-1, -1, 2] ]
首先要用排序,为什么呢,我现在可以给出理由,第一就是避免重复值的出现,避免了去重这一步,(看呆会的操作就知道了) 第二是算法用三指针法 二指针和三指针在移动的时候就是根据大小来移动的。
这道题稍微难一些,可以理解为 二数之和 是双指针法,三数之和 是三指针法
首先第一个指针从i=0到size()-1没什么好说的,然后第二个指针从i+1开始 到尾指针结束,第三个自然是尾指针,二指针三指针之和加起来为target-nums[i] 然后两个指针不断移动, 如果 三个加起来大于target 那么说明尾指针太大了,如果小于0,说明头指针太小了,那么自然是要相应的往中间靠,那么往中间靠的过程。如果是碰上了加起来等于target的值,自然是要指针相应移动,但是下一个值和当前值相同,怎么办? 解决办法就是,判断当前值和下一个值相同否,相同继续移动
(来源:代码随想录)
侵删!
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());
        int len = nums.size()-1;
        for(int i =0;i<=len-3;i++){
            //如果都连在一起了肯定就不用了下一次了
            for(int j = i+1;j<=len-2;j++){
                int left = j+1;
                int right = len;
                while(left<right){
                    int a = nums[i]+nums[j]+nums[left]+nums[right];
                    if(a==target){
                        vector<int> temp = {nums[i],nums[j],nums[left],nums[right]};
                        result.push_back(temp);
                        while (right>i &&nums[right-1]==nums[right]) {
                        //如果需要下一个和当前的相同,那我肯定要让他继续移动啊
                        right--;
                        // cout<<right<<"right="<<endl;
                        }
                        while( left<len && nums[left+1]==nums[left]){
                        left++;
                        // cout<<left<<"left="<<endl;
                        }
                        right--;
                        left++;
                        continue;//移动完成后就交给下一轮去做把
                    }
                    if(a>0){
                        right--;
                    }
                    if(a<0){
                        left++;
                    }
                }

            }
            while(i<len&&nums[i]==nums[i+1]){
                i++;
            }

        }
        return result;
    }
};

四数之和

没什么好说的 再套一层循环,同时避免越界就好

总结

数组篇总结:
第一自然是双指针法
然后就是一些vector的构造

vector构造的例子

vector():创建一个空vector
vector(int nSize):创建一个vector,元素个数为nSize
vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
vector(const vector&):复制构造函数
vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中

vector的常用函数

void push_back(const T& x):向量尾部增加一个元素X
void pop_back():删除向量中最后一个元素
iterator begin():返回向量头指针迭代器,指向第一个元素
iterator end():返回向量尾指针迭代器,指向向量最后一个元素的下一个位置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值