LeetCode 704. 二分查找
题目链接:704. 二分查找
题目描述:给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入:nums
= [-1,0,3,5,9,12],target
= 9 输出: 4 解释: 9 出现在nums
中并且下标为 4
主要思想:二分查找
难点:while循环中“=”问题,right/left更新时是否有+-1
int left = 0;
int right = n - 1; //数组长度为n
while(left op1 right) //op1为<或<=
{
int middle = left + (right - left) / 2;
if(nums[middle] > target) right = middle (- 1); //是否-1
else if(nums[middle] < target) left = middle (+ 1); //是否+1
else return middle;
}
return -1;
左闭右闭
思想:左端点和右端点都可以取到
对op1,因为left和right都可以取到,故当他们取“=”是合法的,所以op1为<=
因nums[middle]>target和nums[middle]< target,此时知nums[middle]一定不是所需要的数,所以right和left均不能取到middle值,要比middle值大1或小1,故有+1,-1。
int left = 0;
int right = n - 1; //数组长度为n
while(left <= right) //op1为<或<=
{
int middle = left + (right - left) / 2;
if(nums[middle] > target) right = middle - 1; //是否-1
else if(nums[middle] < target) left = middle + 1; //是否+1
else return middle;
}
return -1;
左闭右开
思想:左端点可以取到和右端点不可以取到
对op1,因为right不可以取到,故当他们取“=”是不合法的,所以op1为<
因nums[middle]>target和nums[middle]< target,此时知nums[middle]一定不是所需要的数,所以right能取到middle值而left不能取到middle值,left要比middle值大1。
int left = 0;
int right = n; //数组长度为n
while(left < right) //op1为<或<=
{
int middle = left + (right - left) / 2;
if(nums[middle] > target) right = middle; //是否-1
else if(nums[middle] < target) left = middle + 1; //是否+1
else return middle;
}
return -1;
题目特征
有序数组
无重复元素
总结
判断条件:当前值取到是否合法
LeetCode 27. 移除元素
题目链接:27. 移除元素
题目描述:给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k。
示例 1:
输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2,_,_] 解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
主要思想:快慢指针
fast指针:寻找新数组的元素,新数组就是不包含要删除元素的数组
slow指针:更新新数组
代码实现:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
int slow = 0;
for(int fast = 0; fast < len; fast++)
{
if(nums[fast] != val) nums[slow++] = nums[fast];
}
return slow;
}
};
题目特征
原地改变数组
删除等于val的元素
LeetCode中移除元素扩展题
LeetCode 26.删除排序数组中的重复项
题目链接:26.删除排序数组中的重复项
题目描述:给你一个 非严格递增排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。 - 返回
k
。
解题思路:
双指针思想,fast位于数组第二个位置开始增加一个判断条件即nums[fast-1] != nums[fast]
代码:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int len = nums.size();
int slow = 0;
for(int fast = 0; fast < len; fast++)
{
if(fast == 0) nums[slow++] = nums[fast];
else
{
if(nums[fast-1] != nums[fast]) nums[slow++] = nums[fast];
}
}
return slow;
}
};
题目特征
非严格递增数组
原地改变数组
删除重复元素只保留1个
LeetCode 283.移动零
题目链接:283.移动零
题目描述:给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slow = 0;
for(int fast = 0; fast < nums.size(); fast ++)
{
if(nums[fast] != 0) nums[slow++] = nums[fast];
}
for(int i = slow ; i < nums.size(); i++)
{
nums[i] = 0;
}
}
};
解题思路:
同LeetCode 27.移除元素,不同点在于最后要从slow开始补0
题目特征:
原地改变数组
等于0的元素放在数组末尾
LeetCode 844.比较含退格的字符串
题目链接:844.比较含退格的字符串
题目描述:给定 s
和 t
两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true
。#
代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
示例 1:
输入:s = "ab#c", t = "ad#c" 输出:true 解释:s 和 t 都会变成 "ac"。
解题思路:
双指针法应用,若遇到‘#’,slow--。最后使用substr()函数获取子串判断是否相等。
代码:
class Solution {
public:
bool backspaceCompare(string s, string t) {
int slow1 = 0, slow2 = 0;
int len1 = s.size();
int len2 = t.size();
for(int fast = 0; fast < len1; fast ++)
{
if(s[fast] != '#') s[slow1++] = s[fast];
else {
if(slow1 >= 1) slow1--;
}
}
for(int fast = 0; fast < len2; fast ++)
{
if(t[fast] != '#') t[slow2++] = t[fast];
else
{
if(slow2 >= 1) slow2--;
}
}
if(slow1 == 0 && slow2 == 0) return true;
else if((slow1 != 0 && slow2 == 0) ||(slow2 != 0 && slow1 == 0)) return false;
else {
string ss = s.substr(0,slow1);
string tt = t.substr(0,slow2);
return ss == tt;
}
}
};
题目特征:
删除当前值和前一个值
原地变换
注意点:
若‘#’位于开头,则slow不要--
LeetCode 977.有序数组的平方
题目链接:977.有序数组的平方
题目描述:给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100]
解题思路:
开辟一个新数组ans,将原数组区间分为正区间和负区间,指针i从负数区间中左端开始,指针j从正数区间中右端开始,比较过程中较大的数从右至左依次放置在ans数组中
代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int len = nums.size();
vector<int> ans(len,0);
int i = 0, j = len - 1, p = len - 1;
while(p >= 0)
{
int x = nums[i] * nums[i];
int y = nums[j] * nums[j];
if(x > y) ans[p--] = x, i++;
else ans[p--] = y, j--;
}
return ans;
}
};
题目特征:
非递减数组
元素平方后从小到大排列
双指针题目总结
使用场景:
数组原地变换删除某元素