一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情。
剑指 Offer 63. 股票的最大利润
思路
(贪心) O(n)
由于只允许做一次股票买卖交易,因此我们用minv记录一只股票的最低价格,之后遍历整个prices数组,更新minv和prices[i] - minv的最大值。
时间复杂度分析: O(n)
c++代码
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(!prices.size()) return 0;
int res = 0,minv = INT_MAX;
for(int i = 0; i < prices.size(); i++){
minv = min(minv, prices[i]); //记录一只股票的最低价格
res = max(res, prices[i] - minv);
}
return res;
}
};
剑指 Offer 64. 求1+2+…+n
思路
(递归) O(n)
求1 + 2 + ... + n,但是不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句,因此考虑递归。
递归函数定义: int sumNums(int n)表示求1 + 2 + ... + n。
递归等价式: sumNums(n) = n + sumNums(n - 1)。
递归边界: n == 1时,返回1。但是题目要求不能使用if,while等分支判断,可以考虑利用&&短路运算来终止判断。
时间复杂度分析: O(n)
c++代码
class Solution {
public:
int sumNums(int n) {
int res = n;
n >= 1 && (res += sumNums(n - 1));
return res;
}
};
剑指 Offer 65. 不用加减乘除做加法
思路
(异或) O(1)
通过与运算与异或运算来实现加法运算:
- 1、计算两个数不算进位的结果
(a ^ b) - 2、计算两个数进位的结果
(a & b) << 1 - 3、将两个结果相加,我们发现又要用到加法运算,那么其实我们重复上述步骤就行了,直到一个数变为
0( 不再进位 )则运算全部完成。
时间复杂度分析: O(1)
c++代码
class Solution {
public:
int add(int a, int b) {
while(b){
int x = a ^ b; //计算进位
int y = (unsigned int)(a & b) << 1 ; //计算进位,并防止溢出
a = x;
b = y;
}
return a;
}
};
剑指 Offer 66. 构建乘积数组
思路
(数组) O(n)
由题意可知:B[i]=A[0]×A[1]×…×A[i−1]×A[i+1]×…×A[n−1] 。
因此,我们可以通过两边遍历来实现:
- 1、第一遍正向遍历,求出 B[i]=A[0]×A[1]×…×A[i−1]。
- 2、第二遍反向遍历,求出B[i] *= A[n - 1]×A[n - 2]×…×A[i+1]。
最后我们返回B[]数组即可。
时间复杂度分析: 我们遍历了两次数组,因此时间复杂度为O(n)
c++代码
class Solution {
public:
vector<int> constructArr(vector<int>& a) {
int n = a.size();
vector<int> res(n);
for(int i = 0, p = 1; i < n; i++){ // 第一次算出 res[i] = a[0] * a[1] * ... * a[i - 1]
res[i] = p;
p *= a[i];
}
for(int i = n - 1, p = 1; i >= 0; i-- ){
res[i] *= p; // 第二次算出 res[i] *= a[n - 1] * a[n - 2]*...* a[i + 1]
p *= a[i];
}
return res;
}
};