算法训练——数组操作
写在开始
这是一个比较长久的计划,希望自己能够坚持。我会尽量每日(工作日)在github上打卡算法题,每做完一种题型后我会来CSDN总结一下,复盘在这类题型中遇到的问题,以及常用的解题技巧等等。
今天先总结下目前解决完的第一类题型:数组
涉及到的题目,在leetcode中可以找到对应题目:
完整代码及对应题解已上传至github,链接如下:
https://github.com/Aysamu/Algorithms-NoteBook/tree/master/%E7%8E%8B%E6%B3%BD%E6%9D%BE/%E6%95%B0%E7%BB%84
经典题目总结:
题目名称:54. 螺旋矩阵
题目链接:https://leetcode-cn.com/problems/spiral-matrix/
解题思路:
这一题乍一看有点难度,不是很好想。关键你需要确定这个遍历何时结束,当遇到边界的时候如何转弯。官方题解给的很一般,看到了一篇优质题解:从边界入手,规定每次的路径都是右下左上循环,当有边界碰到一起的时候,所有元素均被遍历到,循环截至。
下面附上完整代码:
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector <int> ans;
if(matrix.empty()) return ans; //若数组为空,直接返回答案
int u = 0; //赋值上下左右边界
int d = matrix.size() - 1;
int l = 0;
int r = matrix[0].size() - 1;
while(true)
{
for(int i = l; i <= r; ++i) ans.push_back(matrix[u][i]); //向右移动直到最右
if(++ u > d) break; //重新设定上边界,若上边界大于下边界,则遍历遍历完成,下同
for(int i = u; i <= d; ++i) ans.push_back(matrix[i][r]); //向下
if(-- r < l) break; //重新设定有边界
for(int i = r; i >= l; --i) ans.push_back(matrix[d][i]); //向左
if(-- d < u) break; //重新设定下边界
for(int i = d; i >= u; --i) ans.push_back(matrix[i][l]); //向上
if(++ l > r) break; //重新设定左边界
}
return ans;
}
};
题目名称:118. 杨辉三角
题目链接:https://leetcode-cn.com/problems/pascals-triangle/
解题思路:
较为常见的一类题型,仔细观察可以发现,将三角中的每一行左对齐,空余位置补零,则可形成一个numRows*numRows的矩阵。对于矩阵中的一个元素array[i] [j]来说,其值等于array[i-1] [j]加上array[i-1] [j-1]。若下标越界则按零处理,注意杨辉三角的尖尖,也就是矩阵的[0] [0]号位需要事先置为一。
完整代码:
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> answer;
int array1[numRows][numRows]; //将杨辉三角向左对齐,空的位置补零,则成为一个矩阵,每个元素等于array1[i-1][j-1]+array1[i-1][j];
memset(array1,0,sizeof(array1));
array1[0][0]=1; //杨辉三角的尖尖需要初始化为1。
for(int i=1;i<numRows;i++){
for(int j=0;j<numRows;j++){
int left_head=0;
int right_head=0;
if(i-1>=0){ //注意边界情况下的求值
right_head= array1[i-1][j];
if(j-1>=0){left_head=array1[i-1][j-1];}
}
array1[i][j] = left_head+right_head;
}
}
for(int i=0;i<numRows;i++){
vector<int> temp;
for(int j=0;j<=i;j++){
temp.push_back(array1[i][j]);
}
answer.push_back(temp);
}
return answer;
}
};
题目名称:453.最小操作次数使数组元素相等
题目链接:https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements/
解题思路:最初我的思路较为简单,不停的进行排序,将前n-1个数加一,直到全部相等为止,但是时间超限。优秀解法为数学法,将一个数以的所有数加一,等于把这个数减一。计算所有元素减小到最小值的次数总和即可。
完整代码:
class Solution {
public:
int minMoves(vector<int>& nums) {
int length = nums.size();
sort(nums.begin(),nums.end());
int min=nums[0];
int sum=0;
for(int i=0;i<length;i++){
sum+=nums[i]-min;
}
return sum;
}
};
题目名称:645. 错误的集合
题目链接:https://leetcode-cn.com/problems/set-mismatch/
解题思路:这个做法很新奇,声明一个和原数组一样大小的数组,遍历原数组,利用原数组中的数组值作为新数组的下标,对应数值加一。遍历一遍以后,新数组值为零处代表该下标元素缺少,为2处代表冗余。
完整代码:
class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
vector<int> n(nums.size(),0);
vector<int> res(2,0);
for(int i=0;i<nums.size();i++){
n[nums[i]-1]++;
}
for(int i=0;i<nums.size();i++){
if(n[i]==2) res[0]=i+1;
else if(n[i]==0) res[1]=i+1;
}
return res;
}
};
常用方法总结
Vector数组用法集合
初始化:
一维数组:vector<int> n(nums.size(),0)
,数组大小nums.size(),初始值全部为零。
二维数组:vector<vector<int>> matrix(r,vector<int>(c))
,前面是行数后面是列数,共r行c列,这里初始化的方法比较新奇。
动态添加内容:
不需要事先声明数组大小,利用push_back语句将元素压入vector数组中。
vector<int> temp;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
temp.push_back(nums[i][j]);
}
}
周洋学长总结的vector用法,非常详细,原帖在这里:
https://blog.csdn.net/qq_43549752/article/details/90740440?spm=1001.2014.3001.5501
求数组的大小:
一维数组:int m=nums.size();
二维数组:
int m=nums.size(); //矩阵的行数
int n=nums[0].size(); //矩阵的列数
数组排序:
语句操作,无需二次赋值
sort(nums.begin(),nums.end());
数组拷贝:
将newArr数组中的内容拷贝至nums数组中,注意赋值。
nums.assign(newArr.begin(), newArr.end());
*注:文本部分代码来自leetcode优秀题解,仅总结归纳使用,侵删
created by ZesongWang