重庆网站开发哪家专业页面seo优化
238. 除自身以外的数组乘积
第一眼就是求总乘积,然后除自身,但题目要求不能用除法;
除自身以外,就是左右两边子数组,那不就是一个前缀乘积*后缀乘积吗,逻辑就出来,前缀i-1✖后缀i+1,就好了,不过注意两边极值,第一次写就是极值弄错了。
class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int len = nums.size();vector<int> Lnum(len), Rnum(len);vector<int> result(len);Lnum[0] = nums[0];for(int i=1;i<len-1; i++){Lnum[i] = Lnum[i-1]*nums[i];}Rnum[len-1] = nums[len-1];for(int i=len-2; i>=0; i--)Rnum[i] = Rnum[i+1]*nums[i];for(int i=1;i<len-1;i++){result[i] = Rnum[i+1] * Lnum[i-1];}result[0] = Rnum[1];result[len-1] = Lnum[len-2];return result;}
};
41. 缺失的第一个正数
这题直接哈希了,map一下所有整数,先看有没有1,没有就直接返回1,其次遍历,找有没有比自己大1的键,就好了。
class Solution {
public:int firstMissingPositive(vector<int>& nums) {map<int,int> ma;int result = 0;for(const auto& n :nums){if(n>0 && ma.find(n)==ma.end())ma.insert(make_pair(n,1));}if(ma.find(1) == ma.end()){result = 1;return result;}for(const auto& m : ma){if(ma.find((m.first)+1) == ma.end()){result = (m.first)+1;cout<<m.first<<endl;break;}}return result;}
};
73. 矩阵置零
很容易想到,设置标志位表示原始值是不是0,然后两层for判断,是true就把行、列变为0。但实现起来怎么变为0呢,总不能再加一层for吧。纠结了半天;
其实,标志位不用设置二维,只需要确定某行、某列是否需要设置为0即可。
class Solution {
public:void setZeroes(vector<vector<int>>& matrix) {//vector<vector<bool>> flag(matrix.size(), vector<bool> (matrix[0].size(), false));vector<bool> row(matrix.size()), col(matrix[0].size());for(int i=0;i<matrix.size();i++)for(int j=0;j<matrix[0].size();j++)if(matrix[i][j] == 0)row[i] = col[j] = true;for(int i=0;i<matrix.size();i++)for(int j=0;j<matrix[0].size();j++){if(row[i] || col[j]){matrix[i][j] = 0;}}return;}
};
54. 螺旋矩阵
这是真考验数组边界判定的题,思路很直观,就是按照要求顺时针遍历,涉及4个边界。
class Solution {
public:vector<int> spiralOrder(vector<vector<int>>& matrix) {vector<int> result;if(matrix.empty())return result;int u=0, d=matrix.size()-1, l=0, r=matrix[0].size()-1;while(true){for(int i=l;i<=r;i++)result.push_back(matrix[u][i]);if(++u>d)break;for(int i=u;i<=d;i++)result.push_back(matrix[i][r]);if(--r<l)break;for(int i=r;i>=l;i--)result.push_back(matrix[d][i]);if(--d<u)break;for(int i=d;i>=u;i--)result.push_back(matrix[i][l]);if(++l>r)break;}return result;}
};
53. 最大子数组和
两种思路,动态规划,dp[i]表示i之前的最大子数组之和,每次取+或者不+num[i]的中较大值就好。然后遍历dp,找最大值就行。代码可以优化,求dp时顺便把result也更新。
class Solution {
public:int maxSubArray(vector<int>& nums) {int pre = 0;int result = nums[0];for(const auto& x : nums){pre = max(pre+x, x);result = max(result, pre);}return result;}
};
方法二,正常数组做法,不过就是求和时判断是否为负,如果为负值,那一定会影响最大子数组的和,因此一定不是答案,就更新和为0,重新开始求和;这里也坑,第一次写,想简化逻辑,结果写扯了,写的结果是所有正数之和。。。还感觉自己逻辑没问题,排查了半天。
class Solution {
public:int maxSubArray(vector<int>& nums) {int result = INT_MIN;int add = 0;for(int i=0; i<nums.size(); i++){add += nums[i];if(add>result)result = add;if(add<0)add = 0;}return result;}
};
56. 合并区间
这题很直观,就是根据每个区间的左边界进行排序,然后依次判断即可。
第一个区间的左边界是可以确定的,所以第一个区间放进去。从第二个区间开始判断(i),如果i得左边界小于result得右边界,说明有重叠,更新back得右边界为最大值即可。如果大于,那就没重叠,把i区间放入result即可
class Solution {
public:vector<vector<int>> merge(vector<vector<int>>& intervals) {sort(intervals.begin(), intervals.end());vector<vector<int>> result;result.emplace_back(intervals[0]);for(int i=1; i<intervals.size(); i++){if(result.back()[1] >= intervals[i][0])result.back()[1] = max(result.back()[1], intervals[i][1]);elseresult.emplace_back(intervals[i]);}return result;}
};
48.旋转矩阵
有点抽象了,两种方法,第一种,找出反转后得行列变换规律,matrix[row][col],在旋转后,它的新位置为 new [col][n−row−1]。两层for遍历就好;第二种方法原地反转,不借用辅助空间,顺时针旋转90=水平翻转+主对角线反转。第一次写有些难想到
class Solution {
public:void rotate(vector<vector<int>>& matrix) {int n = matrix.size();auto matrix_new = matrix;for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {matrix_new[j][n - i - 1] = matrix[i][j];}}matrix = matrix_new;}
};
240. 搜索二维矩阵Ⅱ
直接暴力就不说了,优化的话,每行有个二分搜索吧
class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {for(const auto& row:matrix){auto it = lower_bound(row.begin(), row.end(), target);if(it != row.end() && *it==target)return true;}return false;}
};