1.旋转图像
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int pos1=0, pos2=matrix.size()-1;
while(pos1<pos2){
int add=0; //偏移量
while(pos1+add<pos2){
int tmp=matrix[pos1][pos1+add];
matrix[pos1][pos1+add]=matrix[pos2-add][pos1];
matrix[pos2-add][pos1]=matrix[pos2][pos2-add];
matrix[pos2][pos2-add]=matrix[pos1+add][pos2];
matrix[pos1+add][pos2]=tmp;
add++; //偏移量每轮加1,使得整行/整列完成旋转
}
pos1++; //缩进到内一侧
pos2--;
}
}
};
2. 除自己以外数组的乘积
思路:除自己以外乘积=自己(当前元素)的左侧乘积*自己的右侧乘积。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int len=nums.size();
vector<int> res(len,1);
int L=1;
for(int i=0; i<len; i++){
res[i]=res[i]*L;
L *= nums[i];
}
int R=1;
for(int i=len-1; i>=0; i--){
res[i]=res[i]*R;
R *= nums[i];
}
return res;
}
};
3.合并区间
- 对 vector<vector<int>> 排序,需要按照先比较区间开始,如果相同再比较区间结束,使用默认的排序规则即可
- 使用双指针,左边指针指向当前区间的开始
- 使用一个变量来记录连续的范围 t
- 右指针开始往后寻找,如果后续的区间的开始值比 t 还小,说明重复了,可以归并到一起,此时更新更大的结束值到 t,直到区间断开,将 t 作为区间结束,存储到答案里
- 然后移动左指针,跳过中间已经合并的区间
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
vector<vector<int>> res;
for(int i=0; i<intervals.size();){
int t=intervals[i][1];
int j=i+1;
while(j<intervals.size() && intervals[j][0]<=t){ //如果后续区间开始值比t小
t = max(t, intervals[j][1]); //更新最大的结束值 -> t
j++;
}
res.push_back({intervals[i][0],t});
i=j; //跳过已经合并的区间
}
return res;
}
};
4.1比特与2比特字符
我们可以对 bits 数组从左到右扫描来判断最后一位是否为一比特字符。
当扫描到第 i 位时,如果 bits[i]=1,那么说明这是一个两比特字符,将 i 的值增加 2。如果 bits[i]=0,那么说明这是一个一比特字符,将 i 的值增加 1。
如果 i 最终落在了bits.size()−1 的位置,那么说明最后一位一定是一比特字符。
class Solution {
public:
bool isOneBitCharacter(vector<int>& bits) {
int i=0;
while(i<bits.size()-1){
i += bits[i] +1;
}
return i==bits.size()-1;
}
};
5. 找到所有数组中消失的数字
- 遍历输入数组的每个元素一次。
- 我们将把 abs(nums[i])-1 索引位置的元素标记为负数。即 nums[abs(nums[i])−1]×−1 。
- 然后遍历数组,若当前数组元素 nums[i] 为负数,说明我们在数组中存在数字 i+1
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> res;
for(int i=0; i<nums.size(); i++){
if(nums[abs(nums[i])-1]>0){
nums[abs(nums[i])-1] *= -1;
}
}
for(int i=1; i<=nums.size(); i++){
if(nums[i-1]>0){
res.push_back(i);
}
}
return res;
}
};
6. 最短无须连续子数组
思路:有一定的单调栈思想。
- 一次扫描:找到无序子数组的最大最小元素
- 找到最小元素正确位置;
- 找到最大元素正确位置。
class Solution {
public:
int findUnsortedSubarray(vector<int>& nums) {
int _max=INT_MIN, _min=INT_MAX;
for(int i=0; i<nums.size()-1; i++){
if(nums[i+1]<nums[i]){
_min=min(_min, nums[i+1]);
_max=max(_max, nums[i]);
}
}
int l, r;
for(l=0; l<nums.size(); l++){
if(nums[l]>_min){
break;
}
}
for(r=nums.size()-1; r>=0; r--){
if(nums[r]<_max){
break;
}
}
return r-l+1>0 ? r-l+1 : 0;
}
};