2021力扣刷题--数组篇

简单篇

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

<C code>

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int i = 0;
    int j = 0;
    int* ret = (int*)malloc(sizeof(int)*2);

    for(i=0; i<numsSize; i++)
    {
        for(j=i+1; j<numsSize; j++)
        {
            if((nums[i]+nums[j]) == target)
            {
                ret[0] = i;
                ret[1] = j;
                *returnSize = 2;
                return ret;
            }
        }
    }
    *returnSize = 0;
    return NULL;
}

 <C++ code>

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int n = nums.size();
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                if(nums[i]+nums[j]==target)
                {
                    return {i,j};
                }
            }
        }
        return {};
    }
};

53. 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

【核心思想:tmp每次记录以 i 下标为结尾的子数组的最大和】

class Solution {    //时间O(n) 空间O(1)
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        int ret = nums[0], tmp = nums[0];

        for(int i=1; i<n; i++)
        {
            tmp = max(nums[i], tmp+nums[i]);//每次tmp记录的是:以i下标结尾的子数组的最大和;
            ret = max(ret, tmp);
        }
        
        return ret;
    }
};

136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

int singleNumber(int* nums, int numsSize){  //时间O(n) 空间O(1)
    int ret = 0;    
    int i;

    for(i=0; i<numsSize; i++)
    {
        ret = ret ^ nums[i];
    }
    return ret;
}
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int n = nums.size();
        int ret;
        sort(nums.begin(), nums.end());
        if(n==1)
        return nums[0];

        for(int i=0; i<n; i+=2)
        {
            if(i==n-1)  //判断是否遍历到最后一个元素
            {
                ret = nums[i];
                break;
            }
            if(nums[i] != nums[i+1])
            {
                ret = nums[i];
                break;
            }
        }
        return ret;
    }
};

169. 多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

class Solution {
public:
    int majorityElement(vector<int>& nums) {    

//法1
        sort(nums.begin(),nums.end());
        return nums[nums.size()/2];

//法2
        unordered_map<int, int> ret;
        for(auto num : nums)
        {
            ret[num]++;

            if(ret[num]>nums.size()/2)
                return num;
        }
        return -1;


//法3   暴力解法;时间复杂度为 O(nlogn)、空间复杂度为 O(logn);
/*        int tmp_d=0,tmp_n=0;
        int ret_d=0,ret_n=0;
        int n=nums.size();
        int i=0;

        sort(nums.begin(),nums.end());

        if(n==1)
            return nums[0];

        for(int i=0; i<n; i++)
        {
            if(i==0)
            {
                tmp_d=nums[i];
                tmp_n++;
                continue;
            }

            if(nums[i]==nums[i-1])
            {
                tmp_n++;
            }
            else
            {
                if(ret_n<=tmp_n)
                {
                    ret_n=tmp_n;
                    ret_d=tmp_d;
                }
                tmp_d=nums[i];
                tmp_n=1;
            }
        }
        if (ret_n < tmp_n)
        {
            ret_d = tmp_d;
        }

        return ret_d;
        */
    }
};

283. 移动零至数组尾端--双指针思想

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

【核心思想:左指针为0元素段的起始位置,且其左侧均为非0数;右指针左侧到做指针(包含左指针位置)均为0】

void moveZeroes(int* nums, int numsSize){
    int left = 0 , right = numsSize-1;
    int i;

    while(left<right)
    {
        if(nums[left] == 0)
        {
            i = left;
            while(i<right)
            {
                nums[i] = nums[i+1];
                i++;
            }
            nums[right--] = 0;
        }
        else if(nums[left] != 0)
        {
            left++;
        }
    }
}
void swap(int* a, int* b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

void moveZeroes(int* nums, int numsSize){
    int left = 0, right = 0;

    while(right<numsSize)
    {
        if(nums[right])
        {
            swap(nums+left, nums+right);
            left++;
        }
        right++;
    }
}

448. 找到所有数组中消失的数字--原地修改

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

进阶:你能在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n = nums.size();
        for(int i=0; i<n; i++){
            int x = (nums[i]-1) % n;
            nums[x] += n; 
        }

        vector<int> v;
        for(int i=0; i<n; i++){
            if(nums[i] <= n){   //注意这里时<=
                v.push_back(i+1);
            }
        }
        return v;
    }
};

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

/*
*暴力解法
*/
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int left = 0, right = 0;
        int n = prices.size();
        int ret = 0;

        for(int i=0; i<n-1; i++){
            if(i!=0 && prices[i]>prices[left]){
            //if(prices[i]>prices[left]){
                continue;
            }
    
            if(prices[i]<prices[i+1]){
                left = i;
                right = i+1;

                while(right<n){
                    ret = max(prices[right]-prices[left], ret);
                    right++;
                }
            }
        }
        return ret;
    }
};
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int minprices = 1e9, ret = 0;
        
        for(int i = 0; i<prices.size(); i++)
        {
            ret = max(ret, prices[i]-minprices);
            minprices = min(minprices, prices[i]);
        }
        return ret;
    }
};

中等篇

11. 盛最多水的容器--双指针思想

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

/* C code */
int maxArea(int* height, int heightSize){

    int i = 0, j = heightSize-1;   //下标从0开始;
    int ret = (j-i) * fmin( height[i], height[j]);
    int tmp;

    while(i<j)
    {
        height[i]<height[j] ? i++ : j--;

        tmp =  (j-i) * fmin(height[i],height[j]);

        ret = fmax(ret,tmp);
        
    }
    return ret;
}
/* C++ code */
class Solution {
public:
    int maxArea(vector<int>& height) {
        int l = 0, r = height.size() - 1;
        int ret = 0;

        while(l<r)
        {
            ret = max( ret, min(height[l], height[r]) * (r-l) );
            height[l]<height[r] ? l++ : r--;
        }
        return ret;
    }
};

15. 三数之和--排序+双指针

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {

        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> ret;

        //if(n<3)
        //    return ret;

        for(int first=0; first<n; first++)  //第1目标a
        {
            if(first>0 && nums[first]==nums[first-1])   //!!!
                continue;

            int third = n-1;    //!!!目标3的标记,要在第2阶循环前设置;
            for(int second=first+1; second<n; second++)   //第2目标b
            {
                if(second>first+1 && nums[second] == nums[second-1])   //!!!
                    continue;

                while(third>second && nums[first]+nums[second]+nums[third]>0)//第3目标c  注意条件!!!
                {
                    third--;
                }

                if(third==second)
                    break;

                if(nums[first]+nums[second]+nums[third] == 0)
                    ret.push_back({nums[first],nums[second],nums[third]});
            }
        }
        return ret;
    }
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于力扣刷题C++常用操作,我可以给你一些常见的操作和技巧: 1. 使用 STL 容器和算法库:STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,包含了许多常用的容器和算法。在力扣刷题中,使用 STL 可以大大提高代码的效率和可读性。例如,vector 可以用来存储动态数组,sort 可以用来排序等等。 2. 使用 auto 关键字:auto 关键字可以自动推导变量类型,可以减少代码量和提高可读性。例如,auto x = 1; 可以自动推导出 x 的类型为 int。 3. 使用 lambda 表达式:lambda 表达式是 C++11 中引入的一种匿名函数,可以方便地定义一些简单的函数对象。在力扣刷题中,使用 lambda 表达式可以简化代码,例如在 sort 函数中自定义比较函数。 4. 使用位运算:位运算是一种高效的运算方式,在力扣刷题中经常会用到。例如,左移运算符 << 可以用来计算 2 的幂次方,右移运算符 >> 可以用来除以 2 等等。 5. 使用递归:递归是一种常见的算法思想,在力扣刷题中也经常会用到。例如,二叉树的遍历、链表的反转等等。 6. 使用 STL 中的 priority_queue:priority_queue 是 STL 中的一个容器,可以用来实堆。在力扣刷题中,使用 priority_queue 可以方便地实一些需要维护最大值或最小值的算法。 7. 使用 STL 中的 unordered_map:unordered_map 是 STL 中的一个容器,可以用来实哈希表。在力扣刷题中,使用 unordered_map 可以方便地实一些需要快速查找和插入的算法。 8. 使用 STL 中的 string:string 是 STL 中的一个容器,可以用来存储字符串。在力扣刷题中,使用 string 可以方便地处理字符串相关的问题。 9. 注意边界条件:在力扣刷题中,边界条件往往是解决问题的关键。需要仔细分析题目,考虑各种边界情况,避免出错误。 10. 注意时间复杂度:在力扣刷题中,时间复杂度往往是评判代码优劣的重要指标。需要仔细分析算法的时间复杂度,并尽可能优化代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值