1480:一维数组动态和
给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i]) 。
请返回 nums 的动态和。
解题思路:
动态和数组的每一个元素是当前元素加上之前元素的和。
具体步骤:
从题中知道输入的是nums数组,要返回nums的动态数组和nums。
- runningSum[0]= mums[0] i=0,不用处理。
- runningSum[i]=suningSum[i-1]+num[i] i>0, 表达为代码形式nums[i]+=nums[i-1],nums[i-1]为上一个元素的动态和。
class Solution {
public:
vector<int> runningSum(vector<int>& nums) {
int n = nums.size();
for(int i =1; i<n;i++){//第一个元素的动态和就是mums[0]因此不用进入循环
nums[i]+=nums[i-1];//nums[i-1]上一个动态和
}
return(nums);
}
};
383. 赎金信
**给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
解题思路:
题目要求使用字符串magazine 中的字符来构建新的字符串 ransomNote,ransomNote 中的每个字符只能使用一次,只需要满足字符串magazine 中的每个英文字母 的统计次数都大于等于ransomNote 中相同字母的统计次数即可。
具体步骤
- 情况1:magazine 的长度小于字符串 ransomNote 的长度,magazine 无法构成
ransomNote,此时直接返回false。 - 其他情况:首先统计magazine 中每个英文字母的次数 cnt[],再遍历ransomNote中每个英文字母的次数,如果发现ransomNote 中存在某个英文字母 的统计次数大于 magazine 中该字母统计次数直接返回 false。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
//情况1 如果ransomNote的组成字符串比magazine多那么肯定不能被magazine的字符构成
if (ransomNote.size() > magazine.size()) {
return false;
}
//其他情况
vector<int> cnt(26);//定义最大容器空间为26(26个英文字母)的vector
for (auto & c : magazine) {//统计magazine字符串中每个字母的数量
cnt[c - 'a']++;
}
for (auto & c : ransomNote) {
cnt[c - 'a']--;//ransomNote的字母是不是都在magazine中存在且少于
if (cnt[c - 'a'] < 0) {
return false;
}
}
return true;
}
};
用到的知识点:
- 哈希表
- C++ 中auto与auto&的区别
412. Fizz Buzz
给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:
answer[i] == “FizzBuzz” 如果 i 同时是 3 和 5 的倍数。
answer[i] == “Fizz” 如果 i 是 3 的倍数。
answer[i] == “Buzz” 如果 i 是 5 的倍数。
answer[i] == i (以字符串形式)如果上述条件全不满足。
示例 :
输入:n = 15
输出:[“1”,“2”,“Fizz”,“4”,“Buzz”,“Fizz”,“7”,“8”,“Fizz”,“Buzz”,“11”,“Fizz”,“13”,“14”,“FizzBuzz”]
解题思路:
给定一个整数n,判断从1到n的每一个整数i是不是3,5的整数,如果不是就输出i的字符串形式,如果i是3的倍数就输出"Fizz" ,如果i是 5 的倍数就输出"Buzz", 如果 i 同时是 3 和 5 的倍数就输出"FizzBuzz" 。
具体步骤
1.判断是否是3的倍数
2.判断是不是5的倍数
3.如果都不是则输出i的字符串形式
class Solution{
public:
vector<string >fizzBuzz(int n){
vector<string>answer;
for(int i= 1;i<=n;i++){
string curr;
if(i%3==0) {
curr+="Fizz";
}
if(i%5==0) {
curr +="Buzz";
}
if(curr.size()==0) {
curr+=to_string(i);
}
answer.emplace_back(curr);//在容器尾部添加一个元素,这个元素原地构造,不需要触发拷贝构造和转移构造。而且调用形式更加简洁,直接根据参数初始化临时对象的成员。
}
return answer;
}
};//需要加分号
知识点:
- emplace_back()和push_back()
876. 链表的中间结点
给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
解题思路
F1(方法1):
链表的缺点在于不能通过下标访问对应的元素。因此我们可以考虑对链表进行遍历,同时将遍历到的元素依次放入数组 A 中。如果我们遍历到了 N 个元素,那么链表以及数组的长度也为 N,对应的中间节点即为 A[N/2]。
class Solution {
public:
ListNode* middleNode(ListNode* head) {
vector<ListNode*> A = {head};
while (A.back()->next != NULL)
A.push_back(A.back()->next);
return A[A.size() / 2];
}
};
相关知识:
- c语言链表
F2:
解题思路:
我们可以对方法一进行空间优化,省去数组 A。我们可以对链表进行两次遍历。第一次遍历时,我们统计链表中的元素个数 N;第二次遍历时,我们遍历到第 N/2 个元素(链表的首节点为第 0 个元素)时,将该元素返回即可。
class Solution {
public:
ListNode* middleNode(ListNode* head) {
int n = 0;
ListNode* cur = head;
while (cur != nullptr) {
++n;
cur = cur->next;
}
int k = 0;
cur = head;
while (k < n / 2) {
++k;
cur = cur->next;
}
return cur;
}
};
F3:
思路和算法
我们可以继续优化方法二,用两个指针 slow 与 fast 一起遍历链表。slow 一次走一步,fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};
1342. 将数字变成 0 的操作次数
给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
解题思路:
num 与 1进行位运算来判断 num 的奇偶性。
记录操作次数时:
-
如果num 是奇数,我们需要加上一次减 1的操作。
如果 num>1,我们需要加上一次除以 2的操作。
然后使num 的值变成⌊num/2⌋ 。重复以上操作直到num=0 时结束操作。
class Solution {
public:
int numberOfSteps(int num) {
int ret = 0;
while (num) {
ret += (num > 1 ? 1 : 0) + (num & 0x01);
num >>= 1;
}
return ret;
}
};
相关知识:
- 位运算
1672. 最富有客户的资产总量
思路与算法:
分别计算每位客户在各家银行托管的资产数量之和,返回这些资产总量的最大值。
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;
}
};