第五天 2021-3-7 每日刷两题
刷题模块:数组 - 简单难度
一、【题】加一
注意if语句的判断,即数组变大特殊情况的处理
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int n=digits.size();
int carry=1;//初始进位为1,正好使得末位+1
int sum=0;
for(int i=n-1;i>=0;i--){
sum=digits[i]+carry;
digits[i]=sum%10;
carry=sum/10;
}
if(carry==1){
digits.emplace_back(digits[n-1]);
for(int i=n-1;i>0;i--)
digits[i]=digits[i-1];
digits[0]=1;
}
return digits;
}
};
大佬解法,妙啊妙啊
- 由于只是末位+1,当没有进位继续发生时,就可以结束算法输出了
- 若循环正常结束则意味着仍有进位,则需要扩大数组,省去了一层判断;
- 若循环未结束,则说明需要进一位,直接digits[i]++即可;
这么一看自己的代码过于麻烦,不是两个数相加,若有进位必然是10。
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
for(int i=digits.size()-1; i>=0; i--)
{
digits[i]++;
if(digits[i] == 10) digits[i] = 0;
else return digits;
}
digits.insert(digits.begin(), 1);
return digits;
}
};
进一步的改进
若发生数组扩大的情况,必然是99…99+1,则执行循环过后变为00…00。
此时只需要将第一位变为1,并在末尾加入0即可。没必要插入元素移动数组操作。
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
for(int i=digits.size()-1; i>=0; i--)
{
digits[i]++;
if(digits[i] == 10) digits[i] = 0;
else return digits;
}
digits[0]=1;
digits.push_back(0);
return digits;
}
};
vector 语法,直接在任意位置插入元素
//在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
a.insert(a.begin()+1, 5);
//在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5
a.insert(a.begin()+1, 3,5);
//b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如b为1,2,3,4,5,9,8,插入元素后为1,4,5,9,2,3,4,5,9,8
a.insert(a.begin()+1,b+3, b+6);
二、【题】合并两个有序数组
自己独立从做不出来到
- 完整解题
- 两处优化
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
//brilliant mind:正着比每次需要移动数组,不如直接倒着比较
int n1=m-1;
int n2=n-1;
int i=m+n-1;
//brilliant mind:while循环内不必再加i的判断条件,有n1和n2保证
while(n1>=0 && n2>=0)
nums1[i--]=nums1[n1]>nums2[n2]?nums1[n1--]:nums2[n2--];
//brilliant mind:只有n1耗尽而n2未耗尽时,才需要将nums2复制过去
while(n1<=0 && n2>=0){
nums1[i--]=nums2[n2--];
}
}
};
写法优化,更短
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i=m--+n---1;
while(m>=0 && n>=0)
nums1[i--]=nums1[m]>nums2[n]?nums1[m--]:nums2[n--];
while(n>=0){
nums1[i--]=nums2[n--];
}
}
};
三、【题】杨辉三角
平淡无奇
注意开设result的时候预设好大小,性能更佳
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> result(numRows);
for(int n=1;n<=numRows;n++){
result[n-1]=vector<int>(n,1);
for(int j=1;j<n-1;j++){
result[n-1][j]=result[n-2][j-1]+result[n-2][j];
}
}
return result;
}
};
四、【题】杨辉三角Ⅱ
模式识别:在末尾预留空间,考虑倒着来
一般解法
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> result(rowIndex+1,1);
for(int i=3;i<=rowIndex+1;i++){
vector<int> temp=result;
for(int j=1;j<i-1;j++)
result[j]=temp[j-1]+temp[j];
}
return result;
}
};
大佬解法:倒着生成就不用担心覆盖值的问题
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> result(rowIndex+1,1);
for(int i=3;i<=rowIndex+1;i++){
for(int j=i-2;j>0;j--)
result[j]=result[j]+result[j-1];
}
return result;
}
};