1.1480 一维动态数组和
示例:
nums = [1,2,3,4]
输出:[1,3,6,10]
解释:动态和计算过程为 [1, 1+2, 1+2+3, 1+2+3+4] 。
我解:
class Solution {
public:
vector<int> runningSum(vector<int>& nums) {
int len = nums.size();
vector<int> sum;
for(int i=1;i<=len;i++)
{
int sumi=0;
for(int j=0;j<i;j++)
{
sumi+=nums[j];
}
sum.push_back(sumi);
}
return sum;
}
};
最笨的解法。时间复杂度:O(n^2) 空间复杂度:O(n)
优解:
class Solution {
public:
vector<int> runningSum(vector<int>& nums) {
int n = nums.size();
for (int i = 1; i < n; i++) {
nums[i] += nums[i - 1];
}
return nums;
}
};
原地修改。
时间复杂度:O(n),其中 nn 是给定数组长度。
空间复杂度:O(1)。我们只需要常数的空间保存若干变量。
注意⚠️:
vector<int> vec;
for (int i = 0; i < vec.size() - 1; i++)
{
vec[i]
}
这里会有个隐藏问题,当vec的size为0时,因为size()函数的返回值是无符号整型,这时vec.size() - 1是一个正数,导致vec[i]的访问越界
size是指向vector中数组长度后的那一个位置,即size处没有元素
vector下标从0开始
2.1342 数字变0
给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
我解:
class Solution {
public:
int numberOfSteps(int num) {
int times;
for(times=0;num!=0;times++)
{
if(num%2==0&&num!=0){
num/=2;
//times++;
}
else if(num%2!=0&&num!=0){
num-=1;
//times++;
}
}
return times;
}
};
优解:
遇到奇数减一除二、遇到偶数除二,本质上都是二进制的右移,只是奇数需要额外的一步。
出现奇数其实是在右移一定次数后,num & 1 == 1,也就是右移前该位为1。
出现偶数其实是在右移一定次数后,num & 1 == 0, 也就是右移前该位为0。
也就是说,每个二进制位的1都会带来两步的代价,每个二进制位的0都会带来一步的代价。
唯一特殊的是二进制最左的1最后减一为0不需要除二了,所以步数为1。
举个例子:
22 -> 11 -> 10 -> 5 -> 4 -> 2 -> 1 -> 0
10110 -> 1011 -> 1010 -> 101 -> 100 -> 10 -> 1 -> 0
class Solution:
def numberOfSteps(self, num: int) -> int:
return len(b:=bin(num)[2:]) + b.count('1') - 1
3.1672 最富有
给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i 位客户在第 j 家银行托管的资产数量。返回最富有客户所拥有的 资产总量 。
客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。
解
class Solution {
public:
int maximumWealth(vector<vector<int>>& accounts) {
int maxWealth = INT_MIN;
for (auto &account : accounts) {
maxWealth = max(maxWealth, accumulate(account.begin(), account.end(), 0));
}
return maxWealth;
}
};
max accumulate都是内置函数
accumulate带有三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。
accumulate函数将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值。accumulate算法返回累加的结果,其返回类型就是其第三个实参的类型。
可以使用accumulate把string型的vector容器中的元素连接起来:
string sum = accumulate(v.begin() , v.end() , string(" "));
这个函数调用的效果是:从空字符串开始,把vec里的每个元素连接成一个字符串。
4. 412 FizzBuzz
5. 876 链表中间节点
6.383 赎金
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
我解:
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int record[26]={0};
for(int i=0;i<magazine.length();i++)
{
record[magazine[i]-'a']++;
}
for(int j = 0; j < ransomNote.length(); j++)
{
record[ransomNote[j]-'a']--;
if(record[ransomNote[j]-'a']<0)
return false;
}
return true;
}
};
时间复杂度:O(m+n),其中m是字符串 ransomNote 的长度,n 是字符串 magazine的长度,我们只需要遍历两个字符一次即可。
空间复杂度:O(∣S∣),S是字符集,这道题中S为全部小写英语字母,因此 ∣S∣=26