「代码随想录算法训练营」第一天(补) | 数组 part1
704. 二分查找
题目链接:https://leetcode.cn/problems/binary-search/
题目难度:简单
文章讲解:https://programmercarl.com/0704.二分查找.html
视频讲解: https://www.bilibili.com/video/BV1fA4y1o715
题目状态:通过
个人思路:
就是简单的二分查找思路,判断数组中间的值是否等于目标值,不等于就更新范围。
具体代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int low = 0, high = nums.size() - 1;
return Binary(nums, low, high, target);
}
int Binary(vector<int> &nums, int low, int high, int target) {
if(low > high) return -1;
int mid = low + (high - low) / 2;
if(nums[mid] == target) {
return mid;
}
else if(nums[mid] > target) {
return Binary(nums, low, mid - 1, target);
}
else {
return Binary(nums, mid + 1, high, target);
}
}
};
27. 移除元素
题目链接:https://leetcode.cn/problems/remove-element/
题目难度:简单
文章讲解:https://programmercarl.com/0027.移除元素.html
视频讲解: https://www.bilibili.com/video/BV12A4y1Z7LP
题目状态:通过
个人思路:
一开始要打算直接用erase
函数的,但是感觉这应该不是考察的重点,然后就使用了双指针。
- 当左边指针
i
对应的值等于要删除的元素时,将位于右边的指针j
的值覆盖到左边指针,并且j++
; - 当左边指针
i
对应的值不等于要删除的元素时,i++
。
具体代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int i = 0, j = nums.size();
while(i < j) {
if(nums[i] == val) {
nums[i] = nums[j - 1];
j--;
}
else {
i++;
}
}
return j;
}
};
卡哥思路我还真没想过,使用快慢指针
实现代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
int i = 0;
for(int j = 0; j < n; ++j) {
if(val != nums[j]) {
nums[i] = nums[j];
i++;
}
}
return i;
}
};
26. 删除有序数组中的重复项
题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
题目难度:简单
题目状态:通过
个人思路:
学习卡哥上题的思路,使用快慢指针
具体代码:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slow = 0;
for(int fast = 1; fast < nums.size(); ++fast) {
if(nums[slow] != nums[fast]) {
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1;
}
};
283. 移动零
题目链接:https://leetcode.cn/problems/move-zeroes/
题目难度:简单
题目状态:通过
个人思路:
快慢指针太好用了,一次过。
- 使用快指针遍历;
- 当慢指针的值为0,且快指针的值不为0时,快慢指针对应的值交换;
- 当慢指针的值不为0时,将慢指针移动到下一个。
具体代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = 0;
for(int j = 0; j < nums.size(); ++j) {
if(nums[i] == 0 && nums[j] != 0) {
swap(nums[i], nums[j]);
}
if(nums[i] != 0) i++;
}
}
};
844. 比较含退格的字符串
题目链接:https://leetcode.cn/problems/backspace-string-compare/
题目难度:简单
题目状态:没有思路,看题解
当我感觉自己会使用双指针的时候,想法破裂了……
力扣官方题解
1. 栈
当判断一个数组中的元素不为#
时,将该元素入栈;而该元素为#
且栈不为空时,出栈。最终判断两个字符串的栈是否相同。
实现代码如下:
class Solution {
public:
bool backspaceCompare(string s, string t) {
return build(s) == build(t);
}
string build(string s) {
string res;
for(auto i : s) {
if(i != '#') {
res.push_back(i);
}
else if(!res.empty()) {
res.pop_back();
}
}
return res;
}
};
2. 双指针法
先看图解(来自力扣官方):
一个字符是否会被删掉,只取决于该字符后面的退格符,而与该字符前面的退格符无关。因此当我们逆序地遍历字符串,就可以立即确定当前字符是否会被删掉。
具体地,我们定义 skip
表示当前待删除的字符的数量。每次我们遍历到一个字符:
-
若该字符为退格符,则我们需要多删除一个普通字符,我们让
skip
加 1; -
若该字符为普通字符:
- 若
skip
为 0,则说明当前字符不需要删去; - 若
skip
不为 0,则说明当前字符需要删去,我们让skip
减 1。
- 若
这样,我们定义两个指针,分别指向两字符串的末尾。每次我们让两指针逆序地遍历两字符串,直到两字符串能够各自确定一个字符,然后将这两个字符进行比较。重复这一过程直到找到的两个字符不相等,或遍历完字符串为止。
class Solution {
public:
bool backspaceCompare(string S, string T) {
int i = S.length() - 1, j = T.length() - 1;
int skipS = 0, skipT = 0;
while (i >= 0 || j >= 0) {
while (i >= 0) {
if (S[i] == '#') {
skipS++, i--;
} else if (skipS > 0) {
skipS--, i--;
} else {
break;
}
}
while (j >= 0) {
if (T[j] == '#') {
skipT++, j--;
} else if (skipT > 0) {
skipT--, j--;
} else {
break;
}
}
if (i >= 0 && j >= 0) {
if (S[i] != T[j]) {
return false;
}
} else {
if (i >= 0 || j >= 0) {
return false;
}
}
i--, j--;
}
return true;
}
};
977. 有序数组的平方
题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
题目难度:简单
题目状态:之前做过,且已通过
个人思路:
创建一个新数组res
,用来存储结果。
使用双指针分别指向有序数组的两端,并创建一个指针指向res
的尾部。
判断双指针所指的值的平方哪个更大,并将更大的值存入res
。
实现代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size();
vector<int> res(n);
int i = 0, j = n - 1, k = n - 1;
while(i <= j)
{
if(nums[i] * nums[i] > nums[j] * nums[j])
{
res[k] = nums[i] * nums[i];
i++;
}
else
{
res[k] = nums[j] * nums[j];
j--;
}
k--;
}
return res;
}
};