算法通关村第三关---数组

算法通关村第三关—数组

1.LeetCode 896. 单调数列

题目地址:LeetCode

image-20230728214502967

image-20230728214520228

/**
     * 一次遍历
     *
     * @param nums
     * @return
     */
    public boolean isMonotonic(int[] nums) {
        boolean inc = true, dec = true;
        int n = nums.length;
        for (int i = 0; i < n - 1; i++) {
            if (nums[i] > nums[i + 1]) {
                inc = false;
            }
            if (nums[i] < nums[i + 1]) {
                dec = false;
            }
        }
        return inc || dec;
    }

2.LeetCode 35. 搜索插入位置

题目地址:LeetCode

image-20230728214719966

image-20230728214728642

解题思路:

image-20230728215431494

image-20230728215444129

image-20230728215454337

image-20230728215517831

image-20230728215527485

/**
     * 二分查找
     *
     * @param nums
     * @param target
     * @return
     */
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }

3.LeetCode 88. 合并两个有序数组

题目地址:LeetCode

image-20230728215907437

image-20230728215916827

/**
     * 逆向双指针
     *
     * @param nums1
     * @param m
     * @param nums2
     * @param n
     */
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int k = m + n;
        for (int index = k - 1, nums1Index = m - 1, nums2Index = n - 1; index >= 0; index--) {
            if (nums1Index < 0) {
                //nums1已经取完,完全取nums2的值即可
                nums1[index] = nums2[nums2Index--];
            } else if (nums2Index < 0) {
                //nums2已经取完,完全取nums1的值即可
                break;
            } else if (nums1[nums1Index] > nums2[nums2Index]) {
                //nums1的元素值大于nums2,取nums1值
                nums1[index] = nums1[nums1Index--];
            } else {
                //nums2的元素值大于nums1,取nums2值
                nums1[index] = nums2[nums2Index--];
            }
        }
    }

4.LeetCode 27. 移除元素

题目地址:LeetCode

image-20230730213012163

image-20230730213025857

解题思路:

image-20230730215548078

  1. 初始化两个指针:slowfast。这两个指针都从数组的开头(索引 0)开始。
  2. 通过fast指针遍历数组,从第一个元素(索引 0)开始,向数组的末尾移动。
  3. 对于fast指针当前指向的元素,检查它是否等于指定的值val
  4. 如果当前元素不等于val,说明我们要保留这个元素在修改后的数组中(因为我们要移除所有的val)。在这种情况下,将该元素复制到slow指针的位置,然后将slow指针移动到下一个位置。这一步骤有效地将非val元素覆盖到数组中原来val的位置。
  5. 如果当前元素等于val,则直接跳过,不做任何处理,然后将fast指针移到下一个元素的位置,slow指针保持不动。
  6. 重复步骤 4 和 5,直到fast指针到达数组的末尾。
  7. 此时slow指针的值表示修改后的新数组的长度,其中所有的val元素已经被移除。
  8. 返回slow的值,即为修改后的数组中不包含val的元素个数。
/**
     * 快慢双指针
     *
     * @param nums 待处理数组
     * @param val  待删元素
     * @return 不重复元素个数
     */
    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];
                slow++;
            }
        }
        return slow;
    }

5.LeetCode 26. 删除有序数组中的重复项

题目地址:LeetCode

image-20230730215736966

image-20230730215750409

解题思路:

  1. 初始化两个指针:slowfast。其中,slow 表示可以放入新元素的位置,初始值为 1(因为索引为 0 的元素不需要管,可以保留在新数组中)。
  2. 使用循环来模拟快指针的移动,fast 指针从索引 0 开始,向数组的末尾移动。
  3. 对于每个 fast 指针指向的元素,检查它是否与上一个位置(slow - 1索引处)的元素相同。
  4. 如果当前元素与上一个元素不相同,说明该元素是新的不重复元素,应该放入新数组中。将该元素复制到 slow 指针的位置,然后将 slow 指针移动到下一个位置。
  5. 如果当前元素与上一个元素相同,则跳过该元素,不将其放入新数组中,继续考察下一个元素。
  6. 重复步骤 4 和 5,直到 fast 指针遍历完整个数组。
  7. 此时 slow 指针的值表示新数组的长度,其中包含了不重复的元素。
  8. 返回 slow 的值作为新数组的长度。
/**
     * 快慢双指针
     *
     * @param nums 待处理数组
     * @return
     */
    public static int removeDuplicates(int[] nums) {
        //slow表示可以放入新元素的位置,索引为0的元素不用管
        int slow = 1;
        //循环起到了快指针的作用
        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != nums[slow - 1]) {
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }

6.LeetCode 905. 按奇偶排序数组

题目地址:LeetCode

image-20230801191941649

image-20230801192024487

解题思路:

image-20230801193619993

  1. 创建两个指针 leftright,分别初始化为数组的开头和结尾。
  2. 目标是将所有偶数移到数组的左侧,将所有奇数移到数组的右侧。
  3. 进入一个 while 循环,循环条件是 left 小于 right
  4. 在循环中:
    • 检查索引 left 处的数是否为奇数(nums[left] % 2 == 1),以及索引 right 处的数是否为偶数(nums[right] % 2 == 0)。
    • 如果上述条件为真,则交换索引 leftright 处的数,这样就把偶数移到了左侧,把奇数移到了右侧。
    • 如果索引 left 处的数是偶数,则将 left 增加1;如果索引 right 处的数是奇数,则将 right 减少1。这样我们可以继续向数组中心移动,继续交换偶数和奇数。
  5. while 循环结束时,数组将按照奇偶性进行了分区,偶数位于数组的左侧,奇数位于数组的右侧。
  6. 返回排序后的数组。
/**
     * 对撞型双指针
     *
     * @param nums
     * @return
     */
    public int[] sortArrayByParity(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            if (nums[left] % 2 > nums[right] % 2) {
                int temp = nums[right];
                nums[right] = nums[left];
                nums[left] = temp;
            }
            if (nums[left] % 2 == 0) left++;
            if (nums[right] % 2 == 1) right--;
        }
        return nums;
    }

7.LeetCode 189. 轮转数组

题目地址:LeetCode

image-20230801194728585

解题思路:

image-20230801200043716

public void rotate(int[] nums, int k) {
        k %= nums.length;
        reverse(nums, 0, nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }

    public void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[end];
            nums[end] = nums[start];
            nums[start] = temp;
            start++;
            end--;
        }
    }

8.LeetCode 228. 汇总区间

题目地址:LeetCode

image-20230802215508636

image-20230802215613085

解题思路:

慢指针指向每个区间的起始位置,快指针从慢指针位置开始向后遍历直到不满足连续递增(或快指针达到数组边界),则当前区间结束;然后将 slow指向更新为 fast + 1,作为下一个区间的开始位置,fast继续向后遍历找下一个区间的结束位置,如此循环,直到输入数组遍历完毕

/**
     * 快慢指针
     *
     * @param nums
     * @return
     */
    public List<String> summaryRanges(int[] nums) {
        ArrayList<String> res = new ArrayList<>();
        // slow 初始指向第 1 个区间的起始位置
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++) {
            // fast 向后遍历,直到不满足连续递增(即 nums[fast] + 1 != nums[fast + 1])
            // 或者 fast 达到数组边界,则当前连续递增区间 [slow, fast] 遍历完毕,将其写入结果列表
            if (fast + 1 == nums.length || nums[fast] + 1 != nums[fast + 1]) {
                // 将当前区间 [slow, fast] 写入结果列表
                StringBuilder sb = new StringBuilder();
                sb.append(nums[slow]);
                if (slow != fast) {
                    sb.append("->").append(nums[fast]);
                }
                res.add(sb.toString());
                // 将 slow 指向更新为 fast + 1,作为下一个区间的起始位置
                slow = fast + 1;
            }
        }
        return res;
    }

9.剑指 Offer 05. 替换空格

题目地址:剑指 Offer

image-20230802222536210

/**
     * 字符串拼接
     *
     * @param s
     * @return
     */
    public String replaceSpace(String s) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ' ') {
                sb.append("%20");
            } else {
                sb.append(s.charAt(i));
            }
        }
        return sb.toString();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值