27.移除元素
题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
方法
本题特性:数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
代码
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) {
var left = 0;
for (var right = 0;right < nums.length;right++){
if (nums[right] !== val){
nums[left] = nums[right];
left++;
}
}
return left;
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
26.删除排序数组中的重复项
题目
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 10^4
-104 <= nums[i] <= 10^4
nums 已按 升序 排列
方法
同样是两个指针 left 和 right
right指针:寻找新数组的元素,新数组就是不含重复元素
(可以与前面一个元素进行对比【已经保证升序】,也可以与left进行对比)
left指针:指向更新 新数组的下标位置
right 要领先left一个位置
代码
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
var left = 0;
// 错开,就相当于right - 1的操作
for (var right = 1;right < nums.length;right++){
// nums[right] !== nums[left]同样可以,重点是left放在前面
// 在大脑中模拟一下
if (nums[right] !== nums[right - 1]){
left++;
nums[left] = nums[right];
}
}
return left + 1;
};
283.移动零
题目
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
提示:
1 <= nums.length <= 10^4
-2^31 <= nums[i] <= 2^31 - 1
方法
本题方法同移除元素
覆盖掉值为0的所有值,剩下的元素赋值为0
代码
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
let left = 0;
for (let right = 0;right < nums.length;right++){
if (nums[right] !== 0){
nums[left++] = nums[right];
}
}
for (let i = left;i < nums.length;i++){
nums[i] = 0;
}
};
844.比较含退格的字符串
题目
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
示例 1:
输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。
示例 2:
输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。
示例 3:
输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"。
提示:
1 <= s.length, t.length <= 200
s 和 t 只含有小写字母以及字符 ‘#’
方法
一个字符是否会被删掉,只取决于该字符后面的退格符,而与该字符前面的退格符无关。因此当我们逆序地遍历字符串,就可以立即确定当前字符是否会被删掉。
具体地,我们定义 skip 表示当前待删除的字符的数量。每次我们遍历到一个字符:
若该字符为退格符,则我们需要多删除一个普通字符,我们让 skip 加 1;
若该字符为普通字符:
若 skip 为 0,则说明当前字符不需要删去;
若 skip 不为 0,则说明当前字符需要删去,我们让 skip 减 1。
这样,我们定义两个指针,分别指向两字符串的末尾。每次我们让两指针逆序地遍历两字符串,直到两字符串能够各自确定一个字符,然后将这两个字符进行比较。重复这一过程直到找到的两个字符不相等,或遍历完字符串为止。
作者:LeetCode-Solution
代码
Java
// 思路巧妙 不考虑空间复杂度,可以尝试一下
class Solution {
public boolean backspaceCompare(String s, String t) {
return convert(s).equals(convert(t));
}
private String convert(String s) {
StringBuilder sb = new StringBuilder();
char[] cs = s.toCharArray();
int size = 0;
for (int i = cs.length - 1; i >= 0; i--) {
if (cs[i] == '#') {
size++;
} else if (size == 0) {
sb.append(cs[i]);
} else {
size--;
}
}
return sb.toString();
}
}
JavaScript
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var backspaceCompare = function(s, t) {
return convert(s) == convert(t);
};
var convert = function(str){
let string = "";
let size = 0;
for (let i = str.length - 1;i >= 0;i--){
if (str[i] == '#'){
size++;
} else if (size == 0){
string += str[i];
} else {
size--;
}
}
return string;
}
977.有序数组的平方
题目
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
提示:
1 <= nums.length <= 10^4
-10^4 <= nums[i] <= 10^4
nums 已按 非递减顺序 排序
方法
双指针方法
本题包含负数,非递减的排序方式,存在负数的平方大于正数的平方的情况
采用双指针,左右指针分别指向非递减数组两端,平方后比较大小,大的加入新数组(倒序加入),移动大的元素一端的指针,直到left >right。
代码
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
let left = 0,right = nums.length - 1;
let res = new Array(nums.length).fill(0);
let n = nums.length - 1;
while (left <= right){
if (nums[left] * nums[left] < nums[right] * nums[right]){
res[n] = nums[right] * nums[right];
n--;
right--;
}else {
res[n] = nums[left] * nums[left];
n--;
left++;
}
}
return res;
};