二分查找
lc704
c
复制代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while(left < right){
int mid = (left + right) >> 1; // 可以写成mid = left + (right - left) >> 1
if(nums[mid] >= target){
right = mid;
}else{
left = mid + 1;
}
}
if(nums[left] == target){
return left;
}
return -1;
}
};
lc35
c
复制代码
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
// 找第一个>=target的位置
int left = 0, right = nums.size();
while(left < right){
int mid = (left + right) >> 1;
if(nums[mid] >= target){
right = mid;
} else{
left = mid + 1;
}
}
return left;
}
};
lc34
c
复制代码
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.empty()){
return {-1, -1};
}
// lower_bound和upper_bound,注意二分计算时mid的溢出
// 1. 第一个位置
int left = 0, right = nums.size() - 1;
while(left < right){
int mid = left + (right - left) / 2;
if(nums[mid] >= target){
right = mid;
}else{
left = mid + 1;
}
}
if(nums[left] != target){
// 返回[-1, -1]
return {-1, -1};
}
int first = left; // 记录第一个位置
left = 0, right = nums.size() - 1;
// 2. 最后一个位置
while(left < right){
int mid = left + (right - left + 1) / 2;
if(nums[mid] <= target){
left = mid;
}else{
right = mid - 1;
}
}
// 返回结果
return {first, left};
}
};
lc69
- lc69
- 回忆浮点数二分:保证一定精度内正确;但这题使用整数二分即可
- 代码
c
复制代码
class Solution {
public:
int mySqrt(int x) {
int left = 0, right = 1e9;
while(left < right){
int mid = (right + left + 1) / 2;
if((long long)mid * mid <= x){ // 舍去小数,所以找小于的一边
left = mid;
}else{
right = mid - 1;
}
}
return left;
}
};
lc367
c
复制代码
class Solution {
public:
bool isPerfectSquare(int num) {
// 暴力:遍历所有int看是否平方 == num;所以使用二分简化
int left = 1, right = 1e9;
while(left < right){
int mid = (left + right) >> 1;
if((long long)mid * mid >= num){
right = mid;
}else{
left = mid + 1;
}
}
if((long long)left * left == num){
return true;
}
return false;
}
};
快慢指针
lc27
- lc27
- 暴力解:双重for,遍历到val就全部元素往前移一个位置,时间复杂度为O(n^2)
- 优化思路:弄懂快慢指针含义即可,时间复杂度为O(n)
- fast: 原数组位置,寻找不为val值的元素
- slow:最终的目标数组位置
- 变化:fast指向的不是val的元素放到slow处
- 代码
c
复制代码
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int fast = 0, slow = 0;
for(; fast < nums.size(); fast++){
if(val != nums[fast]){
nums[slow++] = nums[fast];
}
}
return slow;
}
};
lc26
- 题目
- 上一题的变形,主要理解快慢指针的含义和他们之间的关系
- 代码
c
复制代码
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.empty()){
return 0;
}
// 快指针:指向原数组,找到第一个不同的元素
// 慢指针:指向结果数组的位置
// 如果nums[fast] != nums[fast - 1],就把这个不重复元素送到slow位置
int slow = 1, fast = 1;
for(; fast < nums.size(); fast++){
if(nums[fast] != nums[fast -1]){
nums[slow++] = nums[fast];
}
}
return slow;
}
};
lc844
- lc844
- 思路1:利用上面快慢指针的思想,分别得到两个最终的字符串后,再比较,时间复杂度为O(n+m);也可以用栈的思路获取最终的字符串
- 代码:
c
复制代码
class Solution {
public:
bool backspaceCompare(string s, string t) {
// 1. 先去掉退格字符
int change_s = changeString(s);
int change_t = changeString(t);
cout << "s = " << s << " t = " << t << endl;
cout << change_s << ' ' << change_t << endl;
// 2. 比较前几个字符是否相同
if(change_s != change_t){
return false;
}
for(int i = 0; i < change_s; i++){
if(s[i] != t[i]){
return false;
}
}
return true;
}
int changeString(string &str){
// 返回前几个字符是有效的
int slow = 0, fast = 0;
for(; fast < str.size(); fast++){
if(str[fast] == '#'){
if(slow != 0){ // 如果slow已经在开头,不用动
--slow;
}
} else{
str[slow++] = str[fast];
}
}
return slow;
}
};
lc977
- lc977
- 思路:相向指针,因为负数平方从大到小,正数平方从小到大;两个指针比较即两个数的平方比较,大的一个放到目标数组中
- 代码
c
复制代码
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
// 暴力:平方后排序
// for(auto &i : nums){
// i = i * i;
// }
// sort(nums.begin(), nums.end());
// return nums;
// 双指针:两头指针,大的放到后面
int n_size = nums.size() - 1;
vector<int> ret(n_size + 1);
for(int i = 0, j = n_size, pos = n_size; i <= j; ){
if(nums[i] * nums[i] <= nums[j] * nums[j]){
ret[pos--] = nums[j] * nums[j];
j--;
} else{
ret[pos--] = nums[i] * nums[i];
i++;
}
}
return ret;
}
};