针对一系列题目:
题目27.移除元素:
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
例如[3,2,2,3],标准3
解法一:
双指针交换:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int j = nums.size() - 1;//j从后往前检索
for (int i = 0; i <= j; i++) {
if (nums[i] == val) {
swap(nums[i--], nums[j--]);
}
}
return j + 1;
}
};
第一个循环;i=0,swap(nums[0],nums[3]),变成[3,2,2,3],此时i为-1,j为2;
第二个循环:i++,i变成0,检测nums[0]==val等于,执行操作swap(nums[0],nums[2]),变成[2,2,2,3];此时i为-1,j为1;
第三个循环:i++,i为0,检测nums[0]==val不成立,不执行;
第四个循环:i++,i为1,不成立不执行;检测结束,输出[2,2,2,3],个数为j+1=2个。
解法二:双指针快慢指针
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;//慢指针要比正常慢
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (val != nums[fastIndex]) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};
[3,2,2,3]
第一个循环:val=nums[0];所以不执行;
第二个循环:val!=nums[1].执行nums[0]=nums[1],此时slowIndex=1,fastIndex=2;
第三个循环:val!=nums[2],执行nums[1]=nums[2];此时slowIndex=2,fastIndex=3;
第三个循环:val=nums[3],不执行,输出slowIndex
题目283:移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
自己解法:结果时间超出限制
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowIndex=0;
int fastIndex;
for(fastIndex=0;fastIndex<nums.size();fastIndex++)
{
if(nums[fastIndex]==0)
{
swap(nums[slowIndex],nums[fastIndex+1]);
fastIndex--;
}
else
slowIndex=slowIndex++;
}
}
};
分析过程:
1.nums[0]==0,fastIndex=-1,slowIndex=0,swap(nums[0],nums[1]),[1,0,0,3,12];
出现问题,判断不了左侧数据是不是为零,因此还是得靠左侧数据进行判断。
规范代码:
示例:
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int n = nums.size(), left = 0, right = 0;
while (right < n) {
if (nums[right]) {
swap(nums[left], nums[right]);
left++;
}
right++;
}
}
};
分析:
第一次循环:nums[0]=0,right=1;left=0;
第二次循环:nums[1]=1,swap(nums[0],nums[1]);[1,0,0,3,12];r=2,l=1
第三次循环:nums[2]=0,r=3,l=1;[1,0,0,3,12];
第四次循环:nums[3]=3,swap(nums[3],nums[1]),r=4,l=2;[1,3,0,0,12];
第五次循环:nums[4]=12,swap(nums[4],nums[2]),[1,3,12,0,0];
...解决问题。
对自己的代码进行修改:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowIndex=0;
int fastIndex;
for(fastIndex=0;fastIndex<nums.size();fastIndex++)
{
if(nums[fastIndex]!=0)
{
swap(nums[slowIndex],nums[fastIndex]);
slowIndex++;
}
}
}
};
修改好了,能够实现功能。
题目 11
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i])。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
解法一:
class Solution {
public:
int maxArea(vector<int>& height) {
int i = 0, j = height.size() - 1, res = 0;
while(i < j) {
res = height[i] < height[j] ?
max(res, (j - i) * height[i++]):
max(res, (j - i) * height[j--]);
}
return res;
}
};
通过左右往内收缩,测试最大值。
如果height[i]<height[j],输出max和(j-i)*height[i]的最大值,然后i++
解法二:自己编写,思路与之前一样
class Solution {
public:
int maxArea(vector<int>& height) {
int i = 0, j = height.size() - 1, res = 0;
while(i<j){
if(height[i]<height[j])
{
res=max(res,(j-i)*height[i]);
i++;
}
else
{
res=max(res,(j-i)*height[j]);
j--;
}
}
return res;
}
};
能够成功运行。
题目15 三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组
解题思路一:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;//二维动态数组
if(nums.size()<3) return ans;
sort(nums.begin(), nums.end());
if(nums[0]>0) return ans;
int i = 0;
while(i<nums.size()){
if(nums[i]>0) break; // 1楼网友指正,将这个if语句放这里提前终止循环
int left = i+1, right = nums.size()-1;
while(left< right){
// 转换为long long避免加法过程中溢出
//这么做是出于谨慎加之以前没有数据范围提示。现在有范围提示,改成 int 即可。
long long y = static_cast<long long>(nums[i]);
long long x = static_cast<long long>(nums[left]);
long long z = static_cast<long long>(nums[right]);
if(x + y >0-z)
right--;
else if(x + y <0-z)
left++;
else{
ans.push_back({nums[i], nums[left], nums[right]});
// 相同的left和right不应该再次出现,因此跳过
while(left<right&&nums[left]==nums[left+1])
left++;
while(left<right&&nums[right] == nums[right-1])
right--;
left++;
right--;
}
}
// 避免nums[i]作为第一个数重复出现
while(i+1<nums.size()&&nums[i] == nums[i+1])
i++;
i++;
}
return ans;
}
};
双指针先学到这儿吧,太难了,先看后面的。