【算法】数组|元素查找与移除

数组:存放在连续内存空间上的相同类型数据的集合

  • 下标从0开始
  • 内存地址是连续的

正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址,而且数组的元素是不能删的,只能覆盖

一.数组元素查找

LeetCode题目链接:704.二分查找

暴力查(遍历)

  • 思路:如果需要从一个数组中查询到某个元素的下标,第一反应就是遍历所有元素然后进行比较,这也是最普遍通用的方法
  • 代码实现
public int search(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                return i;
            }
        }
        return -1;
    }
  • 时间复杂度:O(n)

二分查找

  • 二分查找前置条件:1.元素无重复 2.元素有序

  • 思路:二分查找就是利用了元素的有序与无重复的特性而走了一个捷径:有规律的猜,从而减少判断的次数,即:取数组中间的元素与目标值进行比较,如果相等则命中,如果小于目标值则判断其必定在猜测元素的右侧(这里假定数组是升序的),反之必定在其左侧,直到命中目标值

  • 代码实现

public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int index = (right - left) / 2 + left;
            if (nums[index] == target) {
                return index;
            } else if (nums[index] > target) {
                right = index - 1;
            } else {
                left = index + 1;
            }
        }
        return -1;
    }
  • 时间复杂度:O(logn)

二.数组元素移除

LeetCode题目链接:27.移除元素

双指针法

  • 思路

    由于题目要求删除数组中等于 val 的元素,因此输出数组的长度一定小于等于输入数组的长度,我们可以把输出的数组直接写在输入数组上。可以使用双指针:右指针 right 指向当前将要处理的元素,左指针 left 指向下一个将要赋值的位置。

    • 如果右指针指向的元素不等于 val,它一定是输出数组的一个元素,我们就将右指针指向的元素复制到左指针位置,然后将左右指针同时右移;

    • 如果右指针指向的元素等于 val,它不能在输出数组里,此时左指针不动,右指针右移一位。

    整个过程保持不变的性质是:区间 [0,left) [0,left) 中的元素都不等于 val。当左右指针遍历完输入数组以后,left 的值就是输出数组的长度。这样的算法在最坏情况下(输入数组中没有元素等于 val),左右指针各遍历了数组一次。

  • 代码实现

 public int removeElement(int[] nums, int val) {
        int n = nums.length;
        int left = 0;
        for (int right = 0; right < n; right++) {
            if (nums[right] != val) {
                nums[left] = nums[right];
                left++;
            }
        }
        return left;
    }
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

双指针优化

  • 思路

    如果要移除的元素恰好在数组的开头,例如序列 [1,2,3,4,5]当 val 为 1 时,我们需要把每一个元素都左移一位。注意到题目中说:「元素的顺序可以改变」。实际上我们可以直接将最后一个元素 5 移动到序列开头,取代元素 1,得到序列 [5,2,3,4],同样满足题目要求。这个优化在序列中 val 元素的数量较少时非常有效。

  • 代码实现

public int removeElement2(int[] nums, int val) {
        int left = 0, right = nums.length;
        while (left <= right) {
            if (nums[left] == val) {
                nums[left] = nums[right];
                right--;
            } else {
                left++;
            }
        }
        return left;
    }
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

你可能感兴趣的:(算法,算法,数据结构,java)