双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
很多同学这道题目做的很懵,就是不理解 快慢指针究竟都是什么含义,所以一定要明确含义,后面的思路就更容易理解了。
删除过程如下:
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
//相向双指针法
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length - 1;
while(right >= 0 && nums[right] == val) right--; //将right移到从右数第一个值不为val的位置
while(left <= right) {
if(nums[left] == val) { //left位置的元素需要移除
//将right位置的元素移到left(覆盖),right位置移除
nums[left] = nums[right];
right--;
}
left++;
while(right >= 0 && nums[right] == val) right--;
}
return left;
}
}
// 相向双指针法(版本二)
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length - 1;
while(left <= right){
if(nums[left] == val){
nums[left] = nums[right];
right--;
}else {
// 这里兼容了right指针指向的值与val相等的情况
left++;
}
}
return left;
}
}
27. 移除元素
简单
提示
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0; // 慢指针,用于记录不等于目标值的元素的位置
// 快指针遍历数组
for (int fast = 0; fast < nums.length; fast++) {
// 如果当前元素不等于目标值,将其移到慢指针位置,然后慢指针和快指针均向前移动
if (nums[fast] != val) {
nums[slow++] = nums[fast];
}
}
return slow; // 返回新数组的长度
}
}
26. 删除有序数组中的重复项
简单
提示
给你一个 非严格递增排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
nums
,使 nums
的前 k
个元素包含唯一元素,并按照它们最初在 nums
中出现的顺序排列。nums
的其余元素与 nums
的大小不重要。k
。class Solution {
public int removeDuplicates(int[] nums) {
int slow = 0; // 慢指针,用于记录不同元素的位置
// 快指针遍历数组
for (int fast = 0; fast < nums.length; fast++) {
// 如果当前元素不等于慢指针位置的元素,将其移到慢指针位置,然后慢指针和快指针均向前移动
if (nums[fast] != nums[slow]) {
nums[++slow] = nums[fast];
}
}
return slow + 1; // 返回新数组的长度
}
}
283. 移动零
简单
提示
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
示例 2:
输入: nums =[0]
输出:[0]
提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
进阶:你能尽量减少完成的操作次数吗?
class Solution {
public void moveZeroes(int[] nums) {
int slow = 0; // 慢指针,用于记录非零元素的位置
// 快指针遍历数组
for (int fast = 0; fast < nums.length; fast++) {
// 如果当前元素不为0,将其与慢指针位置的元素交换,然后慢指针和快指针均向前移动
if (nums[fast] != 0) {
int temp = nums[slow];
nums[slow++] = nums[fast];
nums[fast] = temp;
}
}
}
}
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
只含有小写字母以及字符 '#'
进阶:
O(n)
的时间复杂度和 O(1)
的空间复杂度解决该问题吗?class Solution {
public boolean backspaceCompare(String s, String t) {
s = getTrueChar(s); // 处理字符串s,去除退格符后的真实字符
t = getTrueChar(t); // 处理字符串t,去除退格符后的真实字符
return s.equals(t); // 比较两个处理后的字符串是否相等
}
/**
* 处理字符串,去除退格符后的真实字符
*
* @param a 给定字符串
* @return 处理后的字符串
*/
public String getTrueChar(String a) {
int slow = 0; // 慢指针,用于记录处理后的字符串的位置
// 快指针遍历字符串
for (int fast = 0; fast < a.length(); fast++) {
// 如果当前字符不为'#',将其放入慢指针位置覆盖
if (a.charAt(fast) != '#') {
a = a.substring(0, slow) + a.charAt(fast) + a.substring(slow + 1);
slow++;
} else {
slow = Math.max(0, slow - 1); // 如果当前字符为'#',将慢指针指向前一位,等待后边不为'#'的字符覆盖
}
}
return a.substring(0, slow); // 返回处理后的字符串
}
}
//参考答案
class Solution {
public boolean backspaceCompare(String s, String t) {
s = func(s);
t = func(t);
return s.equals(t);
}
private String func(String s) {
StringBuilder tmp = new StringBuilder();
for (char ch : s.toCharArray()) {
if (tmp.length() > 0 && ch == '#') {
tmp.deleteCharAt(tmp.length() - 1);
} else if (ch != '#') {
tmp.append(ch);
}
}
return tmp.toString();
}
}
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 <= 104
-104 <= nums[i] <= 104
nums
已按 非递减顺序 排序进阶:
O(n)
的算法解决本问题//利用非递减顺序,比较两头的平方哪个更大放入数组中
class Solution {
public int[] sortedSquares(int[] nums) {
int n = nums.length;
int[] ans = new int[n];
// 使用双指针从两端向中间遍历
for (int i = 0, j = n - 1, pos = n - 1; i <= j;) {
// 比较平方值大小,较大的平方值放在结果数组的末尾
if (nums[i] * nums[i] > nums[j] * nums[j]) {
ans[pos] = nums[i] * nums[i];
++i;
} else {
ans[pos] = nums[j] * nums[j];
--j;
}
--pos;
}
return ans;
}
}