算法训练营——day2移除元素&有序数组平方

1 移除元素-力扣27(简单)

1.1 题目: 移除元素1

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k

用户评测:

评测机将使用以下代码测试您的解决方案:

int[] nums = [...]; // 输入数组
int val = ...; // 要移除的值
int[] expectedNums = [...]; // 长度正确的预期答案。
                            // 它以不等于 val 的值排序。

int k = removeElement(nums, val); // 调用你的实现

assert k == expectedNums.length;
sort(nums, 0, k); // 排序 nums 的前 k 个元素
for (int i = 0; i < actualLength; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有的断言都通过,你的解决方案将会 通过

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2,_,_]
解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。

示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3,_,_,_]
解释:你的函数应该返回 k = 5,并且 nums 中的前五个元素为 0,0,1,3,4。
注意这五个元素可以任意顺序返回。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。

提示:

  • 0 <= nums.length <= 100
  • 0 <= nums[i] <= 50
  • 0 <= val <= 100

1.2 思路及解法

只能覆盖,不能删除

暴力遍历解法

class Solution {
    public int removeElement(int[] nums, int val) {
        int size=nums.length;
        for(int i=0;i

双指针法

//相向双指针法
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;
    }
}

2 删除有序数组中的重复项-力扣27(简单)

2.1 力扣27题(简单)

2.2 思路及解法

算法训练营——day2移除元素&有序数组平方_第1张图片

(图片摘自力扣题解大佬Max)

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums.length==0 || nums==null){
            return 0;
        }
        int low=0;
        int fast=1;
        while(fast

3 移动0力扣283(简单)

3.1 题目:移动03

给定一个数组 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

进阶:你能尽量减少完成的操作次数吗?

3.2 思路与解法

3.2.1 直接覆盖,不考虑交换

class Solution {
    public void moveZeroes(int[] nums) {
        int indexNow = 0;
        int indexNum = 0;

        while(indexNum

3.2.2 考虑交换

class Solution {
    public void moveZeroes(int[] nums) {
        int n = nums.length, left = 0, right = 0;
        while (right < n) {
            if (nums[right] != 0) {
                swap(nums, left, right);
                left++;
            }
            right++;
        }
    }
    
    public void swap(int[] nums, int left, int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
}

3.3 题目进阶(减少交换次数)

//直接覆盖????
class Solution {
    public void moveZeroes(int[] nums) {
        int write = 0;  // 指向当前要写入数字的位置
        int n = nums.length;
        for(int read = 0; read < n; read++){
            if(nums[read] != 0){
                nums[write++]=nums[read];   // 找到非零数字,填入当前写入的位置
            }
        }
        while(write < n)nums[write++] = 0;  // 剩下的位置全部置零,相当于把零后移
    }
}

4 退格字符串-力扣844(简单)

4.1 题目:比较含退格的字符串

给定 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) 的空间复杂度解决该问题吗?

4.2 思路及题解

双指针 i, j 分别指向 末位字符。

用skip1、skip2存放‘#’
1 若当前字符是 #,则 skip 自增 1;
2 若当前字符不是 #,且 skip 不为 0,则 skipS 自减 1;
3 若当前字符不是 #,且 skip 为 0,则代表当前字符不会被消除,我们可以用来和 字符串2中的当前字符作比较。
若对比过程出现字符不匹配的情况,则返回 false,若均匹配,则true。

class Solution {
    public boolean backspaceCompare(String S, String T) {
        int i = S.length() - 1, j = T.length() - 1;
        int skip1 = 0, skip2 = 0;

        while (i >= 0 || j >= 0) {
            while (i >= 0) {
                if (S.charAt(i) == '#') {
                    skip1++;
                    i--;
                } else if (skip1 > 0) {
                    skip1--;
                    i--;
                } else {
                    break;
                }
            }
            while (j >= 0) {
                if (T.charAt(j) == '#') {
                    skip2++;
                    j--;
                } else if (skip2 > 0) {
                    skip2--;
                    j--;
                } else {
                    break;
                }
            }
            if (i >= 0 && j >= 0) {
                if (S.charAt(i) != T.charAt(j)) {
                    return false;
                }
            } else {
                if (i >= 0 || j >= 0) {
                    return false;
                }
            }
            i--;
            j--;
        }
        return true;
    }
}

5 有序数组平方-力扣977(简单)

5.1 题目: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) 的算法解决本问题

5.2 思路解法

5.2.1 脑残解法

//暴力
class Solution {
    public int[] sortedSquares(int[] nums) {
        int[]ret = new int[nums.length];
        for(int i=0;i

5.2.2 双指针双向

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int[] ret = new int[n];
        for (int i = 0, j = n - 1, pos = n - 1; i <= j;) {
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                ret[pos] = nums[i] * nums[i];
                ++i;
            } else {
                ret[pos] = nums[j] * nums[j];
                --j;
            }
            --pos;
        }
        return ret;
    }
}

你可能感兴趣的:(算法学习,算法)