剑指 Offer 21

版权声明

  • LeetCode 系列笔记来源于 LeetCode 题库1,在个人思考的基础之上博采众长,受益匪浅;故今记此文,感怀于心,更多题解及程序,参见 Github2
  • 该系列笔记不以盈利为目的,仅用于个人学习、课后复习及交流讨论;
  • 如有侵权,请与本人联系([email protected]),经核实后即刻删除;
  • 本文采用 署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0) 协议发布;

1. 剑指 Offer 21

  • 考察内容:
    • 双指针;

    • 代码鲁棒性设计:

      • 在2个 while 循环需要考虑2个指针的先后关系;
        • 防止访问数组越界,E.g. [1, 3, 5];
      • 在2个 while 循环需要考虑2个指针的先后关系;
        • 判断是否需要交换元素;
  • 相似问题:策略模式,将判断数组中元素是否属于某一类的代码封装为一个函数,从主函数中解耦,即可解决多个相似问题,实现代码复用,E.g. 判断数组中的某个元素是否为奇数;
    • 将数组中的负数放在前半部分,非负数放在后半部分;
    • 将数组中能被3整除的数放在前半部分,将不能被整除的数放在后半部分;
  • 辅助数组:
    • 时间复杂度: O ( n ) O(n)
    • 空间复杂度: O ( n ) O(n)
  • 双指针:
    • 时间复杂度: O ( n ) O(n)
    • 空间复杂度: O ( 1 ) O(1)

2. 辅助数组

  • 解题思路:
    • 建立一个与原始数组等长的辅助数组;
    • 定义两个变量headbehind,分别指向辅助数组的首部和尾部;
    • 遍历原始数组,若检测到奇数,则将其放置于head指向的位置,否则放置于behind指向的位置;
    • 缺点:空间复杂度高;
// Approach 1: Auxiliary array
class Solution {
    public int[] exchange(int[] nums) {
        if (nums == null)
            throw new RuntimeException("This is an null reference!");
        if (nums.length == 0)
            return nums;
        int[] aux = new int[nums.length];
        int head = 0;
        int tail = nums.length - 1;
        for (int number: nums) {
            if ((number & 1) == 1)
                aux[head++] = number;
            else
                aux[tail--] = number;
        }
        return aux;
    }
}

3. 双指针

  • 解题思路:
    • 定义两个变量aheadbehind,分别指向数组的首部和尾部;
    • 不断向后移动ahead,直至检测到偶数;
    • 不断向前移动behind,直至检测到奇数;
    • 交换2个变量指向的元素;
    • 重复上述步骤,直至2个变量的相对位置为behind<ahead
// Approach 2: two points
class Solution {
    public int[] exchange(int[] nums) {
        if (nums == null)
            throw new RuntimeException("This is an null reference!");
        if (nums.length == 0)
            return nums;
        int head = 0;
        int tail = nums.length - 1;
        while (head < tail) {
            while (head < tail && (nums[head] & 1) == 1) {
                ++head;
            }
            while (head < tail && (nums[tail] & 1) == 0)
                --tail;
            if (head < tail) {
                int temp = nums[head];
                nums[head] = nums[tail];
                nums[tail] = temp;
            }
        }
        return nums;
    }
}

4. Summary

4.1 Java 语法

  • ==!=的优先级高于&,需要加括号;

4.2 算法优化

  • 计算性能优化:判断数值奇偶性应使用位运算,计算速度优于取余运算;

References


  1. https://leetcode-cn.com/u/hqpan/. ↩︎

  2. https://github.com/hqpan/LeetCode. ↩︎

原创文章 134 获赞 65 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Maximize1/article/details/105351423