两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。代码实现看例27
时间复杂度:O(n^2)
空间复杂度:O(1)
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置
代码实现看例题
时间复杂度:O(n)
空间复杂度:O(1)
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
1.暴力解法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int count = nums.size();
for(int i = nums.size() - 1;i >= 0;i--){
if(nums[i] == val && i < nums.size() - 1){
count--;
for(int j = i;j < nums.size() - 1;j++){
nums[j] = nums[j + 1];
}
}
else if(nums[i] == val && i == nums.size() - 1){
count--;
nums[i] = NULL;
}
}
return count;
}
};
2.改进一点点
因为内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
所以
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int count = nums.size();
for(int i = nums.size() - 1;i >= 0;i--){
if(nums[i] == val ){
count--;
for(int j = i + 1;j < nums.size() ;j++){//因为内部主函数是根据返回的const为数组中的元素个数,如果最后一个数是目标数,自然而然会把最后一个数删除
nums[j - 1] = nums[j];
}
}
}
return count;
}
};
3.双指针法
//不改变数组顺序
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for(int fastIndex = 0;fastIndex < nums.size(); fastIndex++){
if(nums[fastIndex] != val){
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
};
//改变数组顺序
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int leftIndex = 0;
int rightIndex = nums.size() - 1;
while(leftIndex <= rightIndex){
while(leftIndex <= rightIndex && nums[leftIndex] !=val){
leftIndex++;
}
while(leftIndex <= rightIndex && nums[rightIndex] == val){
rightIndex--;
}
if(leftIndex < rightIndex){
nums[leftIndex] = nums[rightIndex];
leftIndex++;
rightIndex--;
}
}
return leftIndex;
}
};
给你一个 升序排列 的数组 nums
,请你** 原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k
个元素,那么 nums
的前 k
个元素应该保存最终结果。
将最终结果插入 nums
的前 k
个位置后返回 k
。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
1.暴力解决
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int count = nums.size();
for(int i = nums.size() - 1;i > 0;i--){
if(nums[i] == nums[i - 1]){
for(int j = i;j < count;j++){
nums[j - 1] = nums[j];
}
count--;
}
}
return count;
}
};
2.双指针法
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slowIndex = 0;
for(int fastIndex = 1;fastIndex < nums.size();fastIndex++){
if(nums[fastIndex] != nums[fastIndex - 1]){
nums[slowIndex + 1] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex + 1;
}
};
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
1.双指针法,将非零移到一边,后面直接补零
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowIndex = 0;
for(int fastIndex = 0;fastIndex < nums.size();fastIndex++){
if(nums[fastIndex] != 0){
nums[slowIndex++] = nums[fastIndex];
}
}
for(int i = slowIndex;i < nums.size();i++){
nums[i] = 0;
}
}
};
2.双指针法,遇到0就交换两个数字位置
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowIndex = 0;
for(int fastIndex = 0;fastIndex < nums.size();fastIndex++){
if(nums[fastIndex] != 0){
swap(nums[slowIndex++],nums[fastIndex]);
}
}
}
};
给定 s
和 t
两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true
。#
代表退格字符。
**注意:**如果对空文本输入退格字符,文本继续为空。
要考虑情况很多:1.没有#时,2.第一个字符为#,3.连续两个#,但是前面没有可删数字 , 4.连续两个#,但是前面有可删数字,5.其他情况
1.双指针法,暴力破解
class Solution {
public:
bool backspaceCompare(string s, string t) {
int slowIndex = 0;
int i = s.length(),j = t.length();
for(int fastIndex = 0;fastIndex < s.length();fastIndex++){
if(s[fastIndex] != '#'){
s[slowIndex] = s[fastIndex];
slowIndex++;
}
else if(fastIndex == 0 ||(s[fastIndex - 1] == '#' && slowIndex == 0)){
i--;
}
else{
slowIndex--;
i = i - 2;
}
}
slowIndex = 0;
for(int fastIndex = 0;fastIndex < t.length();fastIndex++){
if(t[fastIndex] != '#'){
t[slowIndex] = t[fastIndex];
slowIndex++;
}
else if(fastIndex == 0 || (t[fastIndex - 1] == '#' && slowIndex == 0)){
j--;
}
else{
slowIndex--;
j = j - 2;
}
}
if(s.substr(0,i) == t.substr(0,j)){
return true;
}
else return false;
}
};
2.重构字符串 主要想到尾插和尾删
class Solution {
public:
bool backspaceCompare(string s, string t) {
return getNewString(s) == getNewString(t);
}
string getNewString(string x){
string s;
for(auto val:x){
if(val != '#'){
s.push_back(val);
}
else if(s.length() > 0){
s.pop_back();
}
}
return s;
}
};
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
1.先平方,在排序
2.扩展一个新空间,双指针法,每次把最大的放进新数组
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int leftIndex = 0,index = nums.size() - 1;
vector<int> v(index + 1);
for(int rightIndex = nums.size() - 1;rightIndex >= leftIndex;){
if(nums[rightIndex] * nums[rightIndex] > nums[leftIndex] * nums[leftIndex]){
v[index--] = nums[rightIndex] * nums[rightIndex];
rightIndex--;
}
else{
v[index--] = nums[leftIndex] * nums[leftIndex];
leftIndex++;
}
}
return v;
}
};