目录
剑指 Offer 48. 最长不含重复字符的子字符串 3. 无重复字符的最长子串
剑指 Offer 57 - II. 和为s的连续正数序列 滑动窗口
数组(11道):
剑指 Offer 04. 二维数组中的查找
注意:本题与主站 240 题相同:https://leetcode-cn.com/problems/search-a-2d-matrix-ii/
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
if(matrix.size()==0) return false;
int i = matrix.size() - 1, j = 0;
while(i >= 0 && j < matrix[0].size())
{
if(matrix[i][j] > target) i--;
else if(matrix[i][j] < target) j++;
else return true;
}
return false;
}
};
剑指 Offer 39. 数组中出现次数超过一半的数字
注意:本题与主站 169 题相同:https://leetcode-cn.com/problems/majority-element/
官方解释五种都不好懂。。。
得看https://cuijiahua.com/blog/2017/12/basis_28.html中的
投票法:数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值:一个是数组的一个数字,一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1;如果下一个数字和我们之前保存的数字不同,则次数减1。如果次数为零,我们需要保存下一个数字,并把次数设为1。由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。
class Solution {
public:
int majorityElement(vector<int>& nums) {
if(nums.empty()){
return 0;
}
// 遍历每个元素,并记录次数;若与前一个元素相同,则次数加1,否则次数减1
int result = nums[0];
int times = 1;
for(int i = 1; i < nums.size(); ++i){
if(times == 0){
// 更新result的值为当前元素,并置次数为1
result = nums[i];
times = 1;
}
else if(nums[i] == result){
times++;
}
else{
times--;
}
}
return result;
}
};
剑指 Offer 03. 数组中重复的数字
//方法一:哈希表
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_map<int, int> map;
for(int num : nums) {
map[num]++;
if(map[num]>1) return num;
}
//注意返回-1;
return -1;
}
};
/*
复杂度分析:
时间复杂度 O(N) : 遍历数组使用 O(N) ,HashSet 添加与查找元素皆为 O(1) 。
空间复杂度 O(N): HashSet 占用 O(N) 大小的额外空间。
*/
方法二:原地交换
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int i = 0;
while(i < nums.size()) {
if(nums[i] == i) {
i++;
continue;
}
if(nums[nums[i]] == nums[i])
return nums[i];
swap(nums[i],nums[nums[i]]);
}
return -1;
}
};
复杂度分析:
时间复杂度 O(N)O: 遍历数组使用 O(N) ,每轮遍历的判断和交换操作使用O(1) 。
空间复杂度 O(1) : 使用常数复杂度的额外空间。
剑指 Offer 66. 构建乘积数组
class Solution {
public:
vector<int> constructArr(vector<int>& a) {
int n = a.size();
// 返回结果的计算
vector<int> b(n, 1);
// 从上到下,左下角的遍历
for(int i = 1; i < n; i++){
b[i] *= b[i-1] * a[i-1];
}
// 累计乘积的结果,用于和b[i] 来计算
int right = 1;
for(int i=n-2;i>=0;i--){
right *= a[i+1];
b[i] *= right;
}
return b;
}
};
lubuladong刷题手把手刷数组题目
167. 两数之和 II - 输入有序数组
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
解题思路:双指针,解题思路见代码注释
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int low = 0, high = numbers.size() - 1;
while (low < high) {
int sum = numbers[low] + numbers[high];
if (sum == target) {
return {low + 1, high + 1};
} else if (sum < target) {
++low;
} else {
--high;
}
}
return {-1, -1};
}
};
26. 删除排序数组中的重复项
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在