Leetcode刷题笔记

本文介绍了几种常见的数组处理问题的算法解决方案,包括最大子序和、两数之和、合并两个有序数组、两个数组的交集II、买卖股票的最佳时机以及重塑矩阵。通过动态规划和哈希映射等方法,高效地解决了这些题目,展示了如何在有限的时间和空间复杂度内找到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

53.最大子序和【easy】

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

示例1
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6

简单题(并不)。这是一道动态规划,借鉴了大佬的思路。
题目理解:
1,如果全是负数或零,取最大的一个数 ;
2,排除第一种情况,最大子序中的第一个数一定是正数
3,从某个数开始计算sum,直至sum为0,再清空子序重新计算sum,留下所有求和过程中sum的最大值(用ans表示)。

算法理解:
使用sum计算从某个数开始的子序合,用ans保存sum达到过的最大值。
sum只管从i往后加,sum<0时就清空sum重新换,ans保存sum的最大值。
这里是引用

int maxdata(vector<int>& nums)
{
    int i=0;
    int sum=0;
    int ans=nums[0];
    for(i=0;i<nums.size();i++)
    {
         sum = sum + nums[i];
         ans = max(sum,ans);
         if(sum<0)
         {
             sum=0;
         }
    }
    return ans;
}

1.两数之和【easy】

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

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

题解:
这个题使用了hashmap,思路如下:
遍历数组,读数字 i :
1,查看hashmap中是否有key=nums[i]对应的value;
2,如果有,就返回key=nums[i]对应的value 以及 i;
如果没有,就把hashmap中存入key=target-nums[i]的value i;

例如nums = [3,2,4], target = 6
1,遍历数字nums[0] = 3
2,查hashmap[3],没找到
,3,将hashmap[9-3] = hashmap[6] =0 存入,如果后面遍历到了数字6,那么就说明6和数组下标为0的数字可以组成target;

值得一提的是,我发现hashmap在赋值的时候默认value等于0,在储存的时候会和下标0混淆,所以我在储存下标的时候使用了“下标+1”,在return的时候再把“1”减掉。

hashmap的使用方法
#include <map>    //导入包
map<int,int> Inthash;   //声明,int-int可以替换成其他数据类型
Inthash[1]=i+1;  //赋值

vector使用方法
#include <vector>
vector<int> nums;   //声明
nums.push_back(val);   //在vector最后添加数据
nums.pop_back()  //从最后删除数据
nums.size()    //返回vector大小

怎么在vector的内部删除某一下标i的元素,??

上代码

vector<int> twoSum(vector<int>& nums, int target)
{
    vector<int> anser;
    map<int,int> Inthash;
    for(int i=0;i<nums.size();i++)
    {
        if(Inthash[nums[i]])
        {
            anser.push_back(Inthash[nums[i]]-1);
            anser.push_back(i);
            return anser;
        }
        else
        {
            Inthash[target-nums[i]]=i+1;
        }
    }
}

88.合并两个有序数组【easy】

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

这个题比较简单,我最开始的方法是用空间换时间,先把nums1和nums2在vector temp中排好序,再把temp赋给nums1.

//空间换时间
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
    vector<int> temp;
    int i=0,j=0;
    while(i<m && j<n)
    {
        if(nums1[i]<nums2[j])
        {
            temp.push_back(nums1[i]);
            i++;
        }
        else
        {
            temp.push_back(nums2[j]);
            j++;
        }
    }
    while(i<m)
    {
        temp.push_back(nums1[i]);
        i++;
    }
    while(j<n)
    {
        temp.push_back(nums2[j]);
        j++;
    }
    nums1.clear();
    nums1 = temp;
    }

另外学习了一个不需要辅助空间的方法。因为nums1的长度刚好等于m+n,nums1中有m和数,nums2有n个数,也就是说合并好的数组的长度是固定的(不删除相同元素),因此可以从最后遍历。

//不换
void merge2(vector<int>& nums1, int m, vector<int>& nums2, int n)
{
    int i=m-1,j=n-1;
    int k=m+n-1;
    while(i>=0 && j>=0)
    {
        if(nums1[i]>nums2[j])
        {
            nums1[k] = nums1[i];
            k--;
            i--;
        }
        else
        {
            nums1[k] = nums2[j];
            k--;
            j--;
        }
    }
    while(i>=0)
    {
        nums1[k] = nums1[i];
        k--;
        i--;
    }
    while(j>=0)
    {
        nums1[k] = nums2[j];
        k--;
        j--;
    }
}

350. 两个数组的交集 II 【easy】

这个题最先想到的办法就是空间换时间,用hashmap做。时间复杂度O(m+n)。
首先遍历第一个数组,把他们放进对应的hashmap中,每出现一次就加一,记录每个数字出现的个数。
然后遍历第二个数组,每遍历一个数字就查询一下hashmap中的记录(是否有这个数),有的话就输出,并且在hashmap中减一。
空间换时间

//空间换时间
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    vector<int> temp;
    map<int,int> mapnum;
    for(int i=0;i<nums1.size();i++)
    {
        mapnum[nums1[i]]++;
    }
    for(int j=0;j<nums2.size();j++)
    {
        if(mapnum[nums2[j]])
        {
            temp.push_back(nums2[j]);
            mapnum[nums2[j]]--;
        }
    }
    return temp;
    }

121. 买卖股票的最佳时机【easy】

看题解学习了一个单调栈解法,制造一个单调递增栈。
我使用一个变量保存了栈底元素,用单调栈的栈顶减去栈低就是利益。
使用一个变量sum计算利益(每进栈一个数就算一次),然后取ans=max(sum,ans),最后留下的ans就是最大利益。
上代码

int maxProfit(vector<int>& prices) {
    stack<int> a;
    int bottom;
    int ans=0;
    int sum=0;
    for(int i=0;i<prices.size();i++)
    {
        if(a.empty()==true)
        {
            a.push(prices[i]);
            bottom=prices[i];
        }
        else
        {

            while(a.empty()==false && a.top()>prices[i])
            {
                a.pop();
            }
            if(a.empty()==true)
            {
                a.push(prices[i]);
                bottom=prices[i];
            }
            else if(a.top()<prices[i])
            {
                a.push(prices[i]);
                sum=a.top()-bottom;
                ans=max(sum,ans);
            }
        }
    }
    return ans;
    }

566.重塑矩阵【easy】

在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。
给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。
如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

这个题比较简单,我的思路是
1.如果前后矩阵的总数字个数不一致,直接return
如果前矩阵的行数等于后矩阵的列数,直接return
2.遍历前矩阵的每一个元素,然后对应的加到后矩阵中。使用一个变量p控制后矩阵换行,当p==后矩阵的列数时,让p=0,把现有的数据加到矩阵中,然后再清空数据。重复操作。

vector<vector<int>> matrixReshape(vector<vector<int>>& mat, int r, int c) {
    vector<int> temp = mat[0];
    if(mat.size()==r || temp.size()*mat.size()!=r*c)
        return mat;

    int p=0;
    vector<vector<int>> ans;  //后矩阵
    vector<int> a;            //后矩阵的每一行
    for(int i=0;i<mat.size();i++)
    {
        temp = mat[i];
        for(int j=0;j<temp.size();j++)
        {
            a.push_back(temp[j]);
            p++;
            if(p==c)
            {
                p=0;
                ans.push_back(a);
                a.clear();
            }
        }
    }
    return ans;
    }

118.杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。

是一个比较笨笨的方法0.0,就是在第一行和第二行的时候单独处理(全为1),下面的每一行:
1,第一个数和最后一个数都是1
2,其他的每个数等于上一行的第j-1和第j个数的和

vector<vector<int > > generate(int numRows)
{
    vector<vector<int > > ans;
    vector<int> line;
    vector<int> temp;
    for(int i=0;i<numRows;i++)
    {
        if(i==0)
        {
            line.push_back(1);
            ans.push_back(line);
            line.clear();
        }
        else if(i==1)
        {
            line.push_back(1);
            line.push_back(1);
            ans.push_back(line);
            line.clear();
        }
        else
        {
            for(int j=0;j<=i;j++)
            {
                if(j==0)
                    line.push_back(1);
                else if(j==i)
                {
                    line.push_back(1);
                    ans.push_back(line);
                    line.clear();
                }
                else
                {

                    temp=ans[i-1];
                    line.push_back(temp[j-1]+temp[j]);
                }
            }
        }
    }
    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值