vector 二维数组_Leetcode刷题——数组与矩阵1

本文提供了一套LeetCode刷题指南,包括了精选题目的来源、刷题策略及技巧,覆盖了数组、矩阵等基础数据结构的经典问题。通过实际代码示例介绍了如何高效解答常见算法题。

我的Leetcode刷题参考题目指北:

1. 牛客网:leetcode专题(为leetcode的前148道题)

2. leetcode的《初级算法》题集

3.leetcode的《高频面试题汇总》题集

4. github上目前见过最好的高频题整理:

https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode%20%E9%A2%98%E8%A7%A3%20-%20%E7%9B%AE%E5%BD%95.md

计划是按照类型来刷,以刷简单题+中等题为主,hard目前不刷。

刷题流程:

至多5分钟思考思路 + 如果有思路尝试自己写代码;如果实在没思路直接看题解,看完之后自己敲代码写一遍;重点在于梳理和复习,我个人而言,手写是最有效的记忆方式。所以会在每次刷那么45678道题结束后,整理思路、重写代码。

数据结构相关

  • 链表

  • 栈和队列

  • 哈希表

  • 字符串

  • 数组与矩阵

  • 位运算

算法思想

  • 双指针

  • 排序

  • 贪心思想

  • 二分查找

  • 分治

  • 搜索

  • 动态规划

  • 数学

所以,从数组与矩阵开始。

今天的7道题选自牛客网,都是数组的简单题。

37060d7d7a32d73843737b486dcf4f9a.png

往下翻有全部的题目描述和对应代码,但实际上更重要的应该是手写的整理和记忆。

f1d39e13507606ea14a4b4b7763e64b2.png

5caad7f9a174c91c914842c1cc23f855.png

fe8cdc2dfb08d4ed916cbf3bd9304580.png

c8620fe9130f79063647b06624388edd.png

b7af69d24ce0fc729385344cd34ffe9b.png

aa2c17e1ec725bc26e1d7ad33d3edeae.png

具体题目和对应代码:

LC138

给定n个非负整数a1,a2,…,an,其中每个数字表示坐标(i, ai)处的一个点。以(i,ai)和(i,0)(i=1,2,3...n)为端点画出n条直线。你可以从中选择两条线与x轴一起构成一个容器,最大的容器能装多少水?
注意:你不能倾斜容器cf4957cf2da5c1edf8667907e3473441.png

例如:

输入 [1,8,6,2,5,4,8,3,7]
输出: 49

class Solution {public:    /**     *      * @param height int整型vector      * @return int整型     */    int maxArea(vector<int>& height) {        // write code here        int l=0;        int r = height.size()-1;        int Max = 0;        while(l            Max = max(Max, (r-l) * min(height[l], height[r]));            height[l]                    }        return Max;    }};

LC123

给定一个数组和一个值,使用就地算法将数组中所有等于这个值的元素删除,并返回新数组的长度。

元素的顺序可以更改。你不用去关心大于当前数组长度的空间里面存储的值

class Solution {public:    int removeElement(int A[], int n, int elem) {        int j = 0;        for (int i = 0; i < n; i++){            if (A[i] != elem){                A[j] = A[i];                j++;            }        }        return j;    }};

LC102

给出一个用二维矩阵表示的图像

返回该图像顺时针旋转90度的结果

扩展:

你能使用原地算法解决这个问题么?

class Solution {public:    void rotate(vector<vector<int> > &matrix) {        //原地算法,所以不可以新建一个matrix        int n = matrix.size();        //先以y=x为轴作对称        for (int i = 0; i < n; i ++){            for (int j = 0; j < matrix[i].size()-i; j++){                swap(matrix[i][j], matrix[n-1-j][n-1-i]);            }        }       //然后以x轴作对称       for (int k = 0; k < n/2 ; k++){           for (int m = 0; m < matrix[k].size(); m++){               swap(matrix[k][m], matrix[n-1-k][m]);           }       }    }};

LC91

给定一个整数n,将数字1到nn^22按螺旋的顺序填入n×n的矩阵

例如:

给出的n=3,

你应该返回如下矩阵:

[↵ [ 1, 2, 3 ],↵ [ 8, 9, 4 ],↵ [ 7, 6, 5 ]↵]
class Solution {public:    /**     *      * @param n int整型      * @return int整型vector>     */    vector<vector<int> > generateMatrix(int n) {        // write code here        vector<vector<int> > matrix(n,vector<int>(n));        int count = 1;        while (count <= n*n){            for (int i = 0; i                for (int j = i; j                     matrix[i][j] = count;                    count++;                }                for (int k = i+1; k                    matrix[k][n-1-i] = count;                    count++;                }                for (int m = n-2-i; m>=i; m--){                    matrix[n-i-1][m] = count;                    count++;                }                for (int l = n-2-i; l>i; l--){                    matrix[l][i] = count;                    count++;                }            }        }                return matrix;    }};

LC74 荷兰国旗问题

现在有一个包含n个物体的数组,其中物体颜色为颜色为红色、白色或蓝色,请对这个数组进行排序,让相同颜色的物体相邻,颜色的顺序为红色,白色,蓝色。

我们用0,1,2分别代表颜色红,白,蓝

注意:

本题要求你不能使用排序库函数

扩展:

一个非常直接的解法是两步的计数排序的算法

首先:遍历一遍数组,记录0,1,2的数量,然后重写这个数组,先将0写入,再将1写入,再将2写入

你能给出一个只用一步,并且能在常数级空间复杂度解决这个问题的算法吗?

class Solution {public:    void sortColors(int A[], int n) {        int zero = 0;        int two = n-1;        for (int i = 0; i            while (A[i]==2 && i < two) swap(A[i], A[two--]);            while (A[i]==0 && i > zero) swap(A[i], A[zero++]);        }    }};

LC30、29

假设你有一个数组,其中第i个元素是某只股票在第i天的价格。
如果你最多只能完成一笔交易(即买一股和卖一股股票),设计一个算法来求最大利润。

class Solution {public:    /**     *      * @param prices int整型vector      * @return int整型     */    int maxProfit(vector<int>& prices) {        // write code here        int min = prices[0];        int profit = 0;        for (int i = 0; i < prices.size(); i++){            if (prices[i] < min) min = prices[i];            profit = max(profit, prices[i]-min);        }        return profit;    }};

假设你有一个数组,其中第i个元素表示某只股票在第i天的价格。
设计一个算法来寻找最大的利润。你可以完成任意数量的交易(例如,多次购买和出售股票的一股)。但是,你不能同时进行多个交易(即,你必须在再次购买之前卖出之前买的股票)。

class Solution {public:    /**     *      * @param prices int整型vector      * @return int整型     */    int maxProfit(vector<int>& prices) {        // write code here        //分析可知,要想利益最大化,就应该每次在波谷买进,波峰卖出,这样利益最大,操作次数最少        //应该是使用动态规划来做可能比较简洁。        int profit = 0;        int n = prices.size();        int changes[n];        for (int i = 1; i < n; i++){            changes[i-1] = prices[i] - prices[i-1];            if (changes[i-1] > 0) profit += changes[i-1];        }        return profit;    }};
### LeetCode C++ 教程和技巧 #### 去重问中的`removeDuplicates` 对于数组中去除重复元素的问,可以采用较为直接的方法来实现。通过遍历输入的整数列表 `nums` ,并利用计数器 `cnt` 来追踪不重复元素的位置。当遇到一个新的唯一值时(即当前元素不同于其前驱),就将其放置于由 `cnt` 指定的新位置处[^1]。 ```cpp class Solution { public: int removeDuplicates(vector<int>& nums) { int cnt = 0; for(int i = 0; i < nums.size(); i++) { if(!i || nums[i] != nums[i - 1]) nums[cnt++] = nums[i]; } return cnt; } }; ``` 此方法的时间复杂度为 O(n),其中 n 是给定数组的长度;空间复杂度则保持在 O(1),因为只用了常量级别的额外存储空间。 #### 解决两数之和(`twoSum`)问 针对已排序数组上的两数求和问,则可应用双指针策略——具体来说是对撞指针法。初始化一对指向序列两端的游标 (`left`, `right`) 并逐步调整它们之间的距离直到找到满足条件的一对数值为止。如果两个端点所指示数字相加的结果大于目标值,则减少右边界;反之增加左边界直至两者相遇或发现解的存在[^3]。 ```cpp class Solution { public: vector<int> twoSum(vector<int>& numbers, int target) { int left = 0, right = numbers.size() - 1; while (left < right) { int sum = numbers[left] + numbers[right]; if (sum > target) { right--; } else if (sum < target) { left++; } else { return {left + 1, right + 1}; } } return {-1, -1}; } }; ``` 该算法同样具有线性的运行时间性能特征O(n),并且不需要任何附加的数据结构支持从而使得内存消耗维持在一个较低水平之上。 #### 实现矩阵旋转功能 为了完成顺时针方向90度旋转操作,可以通过先执行上下反转再沿主对角线交换元素的方式来达成目的。首先迭代处理每一行其对应的镜像行之间数据互换的任务,接着继续遍历整个二维表并对位于不同列但是共享相同索引号的位置实施交叉替换动作[^4]。 ```cpp class Solution { public: void rotate(vector<vector<int>>& matrix) { int n = matrix.size(); // 上下翻转 for(int i=0; i<n/2; ++i){ for(int j=0; j<n; ++j){ swap(matrix[i][j], matrix[n - i - 1][j]); } } // 对角线翻转 for(int i=0; i<n; ++i){ for(int j=0; j<i; ++j){ swap(matrix[i][j], matrix[j][i]); } } } }; ``` 上述过程有效地实现了原地变换的效果,在不影响其他部分的前提下完成了预期转换任务,并且整体效率较高。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值