一、二分查找
1.leetcode704(简单)
题目链接:https://leetcode-cn.com/problems/binary-search/
解题思路:题目已知条件是有序,所以考虑二分查找。
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left <= right)
{
int mid = left+(right-left)/2;
if(target == nums[mid])
return mid;
if(nums[mid] < target)
{
left = mid+1;
}
else
{
right = mid-1;
}
}
return -1;
}
}
2.leetcode35搜索插入位置(简单)
题目链接:力扣
方法1:暴力解法。时间复杂度O(n),空间复杂度O(1)。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
for(int i = 0;i < nums.size();i++)
{
if(nums[i] >= target)
return i;
}
return nums.size();
}
};
方法2:二分查找法。时间复杂度O(logn),空间复杂度O(1)。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left <= right)
{
int mid = left + (right - left)/2;
if(nums[mid] == target)
return mid;
else if(nums[mid] > target)
{
right = mid-1;
}
else
{
left = mid+1;
}
}
return right+1;
}
};
3.leetcode34在排序数组中查找元素的第一个位置和最后一个位置(中等)
题目链接:力扣
解法1:利用二分查找。时间复杂度O(logn),空间复杂度O(1).
主要是找第一个=target的位置和第一个大于target的位置。
#include<iostream>
#include <vector>
using namespace std;
class Solution {
public:
//查找第一个等于target的下标
int binarySearch_equal(vector<int>& nums, int target)
{
int left = 0;
int right = nums.size() - 1;
int ans = nums.size();
while (left <= right)
{
int mid = left + (right - left) / 2;
if (target <= nums[mid])
{
ans = mid;
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return ans;
}
int binarySearch_greater(vector<int>& nums, int target)
{
int left = 0;
int right = nums.size() - 1;
int ans = nums.size();
while (left <= right)
{
int mid = left + (right - left) / 2;
if (target < nums[mid])
{
ans = mid;
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return ans;
}
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.empty() ||target < nums[0] || target > nums[nums.size()-1])
return vector<int>{-1,-1};
else{
int left_val = binarySearch_equal(nums, target);
int right_val = binarySearch_greater(nums, target)-1;
if(left_val <= right_val)
return vector<int>{left_val, right_val};
else
return vector<int>{-1,-1};
}
}
};
解法2:利用STL现成的函数。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int>::iterator it = find(nums.begin(),nums.end(),target);
int left = -1;
int right = -1;
if(it != nums.end())
{
left = it-nums.begin();
int num = count(nums.begin(),nums.end(),target);
right = left+num-1;
}
return vector<int>{left,right};
}
};
4.leetcode69x的平方根(简单)
题目链接:力扣
解法:二分查找。
易错点:注意数的范围,mid*mid可能为long long。
class Solution {
public:
int mySqrt(int x) {
int left = 0;
int right = x;
int ret = -1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if ((long long)mid * mid <= x)
{
ret = mid;
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return ret;
}
};
5.leetcode367有效的完全平方数(简单)
题目链接:力扣
解法:二分查找法
class Solution {
public:
bool isPerfectSquare(int num) {
int left = 0;
int right = num;
while (left <= right)
{
int mid = left + (right - left) / 2;
if ((long long)mid * mid == num)
{
return true;
}
else if ((long long)mid * mid > num)
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return false;
}
};
总结:
寻找刚好相等的的话,直接返回mid;如果像是34或者367一样,等于条件与另一个条件混合在一起的话,设置一个变量ret记录,然后返回。
二、移除元素
1.leetcode27移除元素(简单)
题目链接:力扣
解法:双指针法。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;
for (int fast = 0;fast < nums.size();fast++)
{
if (nums[fast] != val)
{
nums[slow++] = nums[fast];
}
}
return slow;
}
};
2.leetcode26删除有序数组中的重复元素(简单)
题目链接:力扣
解法一:利用双指针法。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slow = 0;
for (int fast = 0;fast < nums.size();fast++)
{
if (fast== 0 ||nums[fast] != nums[fast-1])
{
nums[slow++] = nums[fast];
}
}
return slow;
}
};
解法二:利用STL中的erase函数。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
for(int i = 0;i < nums.size();i++)
{
if(i >0 &&(nums[i] == nums[i-1]))
{
nums.erase(nums.begin()+i);
i--;
}
}
return nums.size();
}
};
解法三:利用STL中的去重函数unique。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
return unique(nums.begin(),nums.end())-nums.begin();
}
};
总结:unique函数原型
unique函数的函数原型如下:只有两个参数,且参数类型都是迭代器:
1 |
|
这种类型的unique函数是我们最常用的形式。其中这两个参数表示对容器中[it_1,it_2)范围的元素进行去重(注:区间是前闭后开,即不包含it_2所指的元素),返回值是一个迭代器,它指向的是去重后容器中不重复序列的最后一个元素的下一个元素。
3.leetcode844比较含退格的字符串(简单)
题目链接:
解法一:双指针法。时间复杂度O(N+M)。空间复杂度O(1)。
//双指针
class Solution {
public:
bool backspaceCompare(string s, string t) {
int i = s.size() - 1;
int j = t.size() - 1;
int sskipNum = 0;
int tskipNum = 0;
while (1)
{
while (i >= 0)
{
if (s[i] == '#')
{
sskipNum++;
}
else
{
if (sskipNum > 0)
{
sskipNum--;
}
else
{
break;
}
}
i--;
}
while (j >= 0)
{
if (t[j] == '#')
{
tskipNum++;
}
else
{
if (tskipNum > 0)
{
tskipNum--;
}
else
{
break;
}
}
j--;
}
if (i < 0 || j < 0) break;
if (s[i] != t[j]) return false;
i--;
j--;
}
if (i == -1 && j == -1)
{
return true;
}
return false;
}
};
解法二:重构字符串法。时间复杂度O(N+M)。空间复杂度O(N+M)。
//重构字符串
class Solution {
public:
bool backspaceCompare(string s, string t) {
return build(s) == build(t);
}
string build(string str)
{
string ret;
for (char ch : str)
{
if (ch != '#')
{
ret.push_back(ch);
}
else if(!ret.empty())
{
ret.pop_back();
}
}
return ret;
}
};
4.leetcode977有序数组的平方(简单)
题目链接:力扣
解法一:双指针法。时间复杂度:O(n),空间复杂度O(1)。
#include <iostream>
#include<vector>
using namespace std;
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int i, j,k;
k = nums.size() - 1;
vector<int> result(nums.size(), 0);
for (i = 0, j = nums.size() - 1;i <= j;)
{
if (nums[i] * nums[i] > nums[j] * nums[j])
{
result[k--] = (nums[i] * nums[i]);
i++;
}
else
{
result[k--]=(nums[j] * nums[j]);
j--;
}
}
return result;
}
};
解法2:暴力解法。stl中的内置函数sort。空间复杂度:O(n+nlogn)。空间复杂度:O(logn)。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for (int i = 0;i < nums.size();i++)
{
nums[i]*=nums[i];
}
sort(nums.begin(), nums.end());
return nums;
}
};
注意:STL中的sort函数的时间复杂度是O(nlogn)。
三、滑动窗口
1.leetcode209长度最小的子数组。(中等)
题目连接:力扣
解法一:暴力解法。时间复杂度O(n^2),空间复杂度O(1)。
#include <iostream>
#include<vector>
using namespace std;
//暴力解法
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = 65535;
int sublength = 0; //子序列长度
for (int i = 0;i < nums.size();i++)
{
int sum = 0;
for (int j = i;j < nums.size();j++)
{
sum += nums[j];
if (sum >= target)
{
sublength = j - i + 1;
result = result < sublength ? result : sublength;
break;
}
}
}
return result == 65535? 0 : result;
}
};
解法二:滑动窗口——双指针。时间复杂度O(n),空间复杂度O(1) .
//滑动窗口——双指针
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int start = 0;
int end;
int sum = 0;
int result = 65535;
int sublength = 0;
for (end = 0;end < nums.size();end++)
{
sum += nums[end];
while (sum >= target)
{
sublength = end - start + 1;
result = result < sublength ? result : sublength;
sum -= nums[start++];
}
}
return result == 65535 ? 0 : result;
}
};
2.leetcode904水果成篮(中等)
题目链接:力扣
解法:滑动窗口
备注:写了很久。。。
#include<iostream>
#include<vector>
#include <map>
using namespace std;
class Solution {
public:
int totalFruit(vector<int>& fruits) {
map<int, int> basket;
int i = 0;
int result = 0;
for (int j = 0;j < fruits.size();++j)
{
basket.insert(pair<int, int>(fruits[j], ++basket[fruits[j]]));
while (basket.size() > 2)
{
--basket[fruits[i]];
if(basket[fruits[i]] == 0)
basket.erase(fruits[i]);
i++;
}
result = result > (j - i + 1) ? result : (j - i + 1);
}
return result;
}
};
3.leetcode76最小覆盖子串(困难)
题目链接:力扣
解法:滑动窗口+哈希表
class Solution {
public:
string minWindow(string s, string t) {
vector<int> need(128, 0);
for (char ch:t)
{
need[ch]++;
}
int left = 0, right = 0,count = t.size(), result = 65535,start = 0;
while (right < s.size())
{
if (need[s[right]] > 0)
{
count--;
}
need[s[right]]--;
if(count == 0)
{
while (left < right && need[s[left]] < 0)
{
need[s[left++]]++;
}
if (right - left + 1 < result)
{
result = right - left + 1;
start = left;
}
need[s[left]]++;
left++;
count++;
}
right++;
}
if(result == 65535)
{
return "";
}
else
return s.substr(start, result);
}
};
注意:
1.在leetcode中解决问题时,所有声明的变量必须在类内。不然会出现测试可以通过,而提交不通过的情况。这次因为把vector<int>在solution类外声明耗费了大量时间找错。
2.substr函数的第二个参数是指要截取的长度。
四、螺旋矩阵
1.leetcode59螺旋矩阵II(中等)
题目链接:力扣
解法:模拟
#include<iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n, vector<int>(n));
int k = 1;
int left = 0, right = n - 1, top = 0, bottom = n - 1;
while (k <= n * n)
{
for (int i = left;i <= right;i++, k++)
{
result[top][i] = k;
}
top++;
for (int i = top;i <= bottom;i++, k++)
{
result[i][right] = k;
}
right--;
for (int i = right;i >= left;i--, k++)
{
result[bottom][i] = k;
}
bottom--;
for (int i = bottom;i >= top;i--, k++)
{
result[i][left] = k;
}
left++;
}
return result;
}
};
2.leetcode 54螺旋矩阵(中等)
题目链接:力扣
解法:模拟
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int rows = matrix.size();
int columns = matrix[0].size();
int count = rows * columns;
vector<int> res;
int k = 0,left = 0, right = columns - 1, top = 0, bottom = rows - 1;
while (k < count)
{
for (int i = left;i <= right&&k < count;++i)
{
res.push_back(matrix[top][i]);
k++;
}
top++;
for (int i = top;i <= bottom&&k < count;++i)
{
res.push_back(matrix[i][right]);
k++;
}
right--;
for (int i = right;i >= left&&k < count;--i)
{
res.push_back(matrix[bottom][i]);
k++;
}
bottom--;
for (int i = bottom;i >= top&&k < count;--i)
{
res.push_back(matrix[i][left]);
k++;
}
left++;
}
return res;
}
};
3.leetcode剑指offer29顺时针打印矩阵(简单)
题目链接:力扣
解法:模拟(与上题相同)
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return {};
}
vector<int> res;
int rows = matrix.size();
int columns = matrix[0].size();
int count = rows * columns;
int left = 0, right = columns - 1, top = 0, bottom = rows - 1, k = 0;
while (k < count)
{
for (int i = left;i <= right&&k<count;++i)
{
res.push_back(matrix[top][i]);
k++;
}
top++;
for (int i = top;i <= bottom&&k < count;++i)
{
res.push_back(matrix[i][right]);
k++;
}
right--;
for (int i = right;i >= left&&k < count ;--i)
{
res.push_back(matrix[bottom][i]);
k++;
}
bottom--;
for (int i = bottom;i >= top && k < count;--i)
{
res.push_back(matrix[i][left]);
k++;
}
left++;
}
return res;
}
};
注意:
需要考虑输入数组为空的情况。判断二维数组为空条件是行数为0或者列数为0且返回空数组的写法是:return {};上题虽然也能通过,但也需要补充这个条件。