之前的blog链接:https://blog.csdn.net/weixin_43303286/article/details/131700482?spm=1001.2014.3001.5501
我用的方法是在leetcode再过一遍例题,明显会的就复制粘贴,之前没写出来就重写,然后从拓展题目中找题目来写。辅以Labuladong的文章看。然后刷题不用CLion了,使用leetcode自带模拟面试环境。
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
自己想出来两种解法,一种是重新使用额外数组,一种是使用先翻转整体再反转局部:
class Solution {
public:
void rotate(vector<int>& nums, int k) {
// //方法1:使用一个新数组
// int n = nums.size();
// vector res;
// k = k % n;
// for(int i = n - k; i < n; i++){
// res.push_back(nums[i]);
// }
// for(int i = 0; i < n - k; i++){
// res.push_back(nums[i]);
// }
// nums = res;
//先整体翻转,再部分reverse
k = k % nums.size();
reverse(nums.begin(), nums.end());
reverse(nums.begin(), nums.begin() + k);
reverse(nums.begin() + k, nums.end());
}
};
官方题解还有一种基于数学推导的:
最终代码:
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
k = k % n;
int count = gcd(k, n);
for (int start = 0; start < count; ++start) {
int current = start;
int prev = nums[start];
do {
int next = (current + k) % n;
swap(nums[next], prev);
current = next;
} while (start != current);
}
}
};
这个我肯定想不出来,但时间复杂度和两次反转一样都是O(n),空间复杂度都是O(1)。
给你一个整数数组 nums,返回 数组 answer ,
其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在32 位 整数范围内。
请 不要使用除法,且在 O(n) 时间复杂度内完成此题。
示例 1:
输入: nums = [1,2,3,4]
输出: [24,12,8,6]
示例 2:
输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]
首先是暴力解法,因为这题不能使用乘法,二重循环遍历,很好想象超时了:
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
vector<int> answer;
int sup;
for(int i = 0; i < nums.size(); i++){
int sup = 1;
for(int j = 0; j < nums.size(); j++){
if(i == j){
continue;
}
sup *= nums[j];
}
answer.push_back(sup);
}
return answer;
}
};
还有一种方法是先求出所有元素的和,再分别/nums[i],这个用了除法肯定是过不了的。
这里使用评论区一个非常巧妙的解法:双指针解法
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> answer(n , 1);
int beforeSum = 1, afterSum = 1;
for(int i = 0, j = n - 1; i < n; i++, j--){
answer[i] *= beforeSum;
answer[j] *= afterSum;
beforeSum *= nums[i];
afterSum *= nums[j];
}
return answer;
}
};
这个思路和之前的接雨水相似,都是从两头逼近,明天把前缀和相关的代码看一遍。