给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。题目链接
**方法1思路:**暴力解法,通过两个for循环来实现,第一个for循环进行数组的便利,找到和val相同的元素时进入第二个for循环,在第二个for循环中实现后方元素对前方元素的覆盖,离开第二个for循环后,将数组长度len–,再将i的值–,因为原位置已经被后面的数据覆盖。
代码如下:
class Solution {
public int removeElement(int[] nums, int val) {
int len = nums.length;
for (int i = 0; i < len; i++){
if (nums[i] == val) {
for (int j = i; j < len-1; j++){
nums[j] = nums[j+1];
}
len--;
i--;
}
}
return len;
}
}
**方法2思路:**只需一个for循环,该for循环用于遍历数组,在数组中新增一个判断条件,如果val不等于该位置的数值,则nums[k] = nums[i],且k++表示向后移动一个位置;如果val等于该位置的数值,则不进行操作。通过这种方式实现对val数值的替换。
代码如下:
class Solution {
public int removeElement(int[] nums, int val) {
int cnt = 0;
for (int i = 0; i < nums.length; i++){
if (nums[i] != val) {
nums[cnt++] = nums[i];
}
}
return cnt;
}
}
方法一和方法二在内存消耗上相近,在时间复杂度上,法二更好。
**方法3思路:**双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。双指针法在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。(此处参考代码随想录)
代码如下:
class Solution {
public int removeElement(int[] nums, int val) {
int fastIndex = 0, slowIndex = 0;
for (fastIndex = 0; fastIndex < nums.length; fastIndex++){
if (nums[fastIndex] != val) { //如果快指针位置的数值和val相等,则将该位置的值赋值给慢指针所在的位置
nums[slowIndex++] = nums[fastIndex];
}
//如果不相等,则不进行任何操作,相当于随着for循环的进行,快指针向后移动而慢指针位置不变
//慢指针所在的位置始终是待替换数值的位置
}
return slowIndex;
}
}
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。题目链接
思路:采用双指针法。注意本题所给的数组是有序数组。和例题1相同,慢指针下一个位置的值都是待替换的,当快指针向后移动时,分为两种情况:
代码如下:
class Solution {
public int removeDuplicates(int[] nums) {
if (nums==null || nums.length == 1){
return nums.length;
}
int slowIndex = 0, flatIndex = 1;
for (; flatIndex < nums.length; flatIndex++){
if (nums[slowIndex] != nums[flatIndex]) {
slowIndex++;
nums[slowIndex] = nums[flatIndex];
}
}
return slowIndex+1;
}
}
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
思路:如果数组为空或者数组长度为1,则不需要调整,直接返回结果即可;如果数组长度大于1,此时遍历数组,将index位置上的数据全部替换为nums数组上不为0的数值;最后,从index位置对数组进行for循环,将index后面的数据全部替换为0.
代码如下:
class Solution {
public void moveZeroes(int[] nums) {
if (nums.length <= 1 || nums == null){
return;
}
int index = 0;
for (int i = 0; i < nums.length; i++){
if (nums[i] != 0){
nums[index++] = nums[i];
}
}
for (int i = index; i < nums.length; i++){
nums[i] = 0;
}
return;
}
}
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,请你判断二者是否相等。# 代表退格字符。
如果相等,返回 true ;否则,返回 false 。
注意:如果对空文本输入退格字符,文本继续为空。题目链接
**方法1思路:**采用栈的思想,创建两个String类型的数组。分别遍历数组s和t,如果该位置字符不为#,则将该字符连接到ss或tt后;如果为#,则将最后一个字符删除。最后对字符进行比较,如果相等返回true,不相等返回false.
代码如下:
class Solution {
public boolean backspaceCompare(String s, String t) {
String ss = "", tt = "";
for (int i = 0; i < s.length(); i++){
if (s.charAt(i) != '#') {
ss = ss + String.valueOf(s.charAt(i));
}
else if (ss.length() != 0){
ss = ss.substring(0, ss.length()-1);
}
}
for (int i = 0; i < t.length(); i++){
if (t.charAt(i) != '#') tt = tt + String.valueOf(t.charAt(i));
else if (tt.length() != 0){
tt = tt.substring(0, tt.length()-1);
}
}
if (ss.compareTo(tt) == 0) return true;
return false;
}
}
方法1有缺陷,执行时间和内存消耗比较大。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ydsDj3BT-1642948952190)(C:\Users\lmh\AppData\Roaming\Typora\typora-user-images\image-20220123132343305.png)]
方法2思路:采用StringBuilder模拟栈,思路和方法1相似(参考代码随想录解析)
class Solution {
public boolean backspaceCompare(String s, String t) {
StringBuilder ssb = new StringBuilder(); // 模拟栈
StringBuilder tsb = new StringBuilder(); // 模拟栈
// 分别处理两个 String
for (char c : s.toCharArray()) {
if (c != '#') {
ssb.append(c); // 模拟入栈
} else if (ssb.length() > 0){ // 栈非空才能弹栈
ssb.deleteCharAt(ssb.length() - 1); // 模拟弹栈
}
}
for (char c : t.toCharArray()) {
if (c != '#') {
tsb.append(c); // 模拟入栈
} else if (tsb.length() > 0){ // 栈非空才能弹栈
tsb.deleteCharAt(tsb.length() - 1); // 模拟弹栈
}
}
return ssb.toString().equals(tsb.toString());
}
}
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。题目链接
思路:双指针法(前后指针),left表示左指针,right表示右指针,将两个指针所指位置数值的平方进行比较并加入到新创建的数组res中。
代码如下:
class Solution {
public int[] sortedSquares(int[] nums) {
if (nums.length == 0) return nums;
int left = 0, right = nums.length-1;
int len = nums.length - 1;
int []res = new int[len+1];
while (left <= right) {
if (nums[left]*nums[left] < nums[right]*nums[right]) {
res[len--] = nums[right] * nums[right];
right--;
}else if (nums[left]*nums[left] > nums[right]*nums[right]){
res[len--] = nums[left] * nums[left];
left++;
}else {
res[len--] = nums[left] * nums[left];
left++;
}
}
return res;
}
}