• 牛客网剑指offer第13题——调整数组顺序使得奇数位于偶数前面


    题目来源:剑指offer

    题目

           输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

    解题思路:

          数组类题目指导原则:除了极其傻瓜式的题目,大部分数组类的题目都要用到 “双索引“策略,只不过有的采用对撞指针,有的采用跟随指针。

         我们随便举出一个数组的例子,才分析怎么做才比较合适:2 4 7 4 3 5 8  10 9;

         那么此时,你会怎么做,当然了,我们当然是需要找出所有的奇数,以及所有的偶数。基于这种找的思想,我们当然可以这么做:从头到尾判定这个数组的每个元素的奇偶性,然后生成一个和该数组同样大小的数组空间,将扫描到的奇数按原顺序放在新数组的前半部分,再将是扫描到的偶数放到新数组的后半部分,毫无疑问,这种策略但从结果上看,是没有任何问题的,问题在于:我们使用了一个和原数组同样大小的数组空间。这使得时间复杂度和空间复杂度都为O(n)可见,这样并不是一个好方法。有没有更好的方法呢?

         当然有:

         请别忘记我们最终要做的是:将奇数按照原来的顺序放到前面,偶数按照原来的顺序放到后面。有没有可能,我们仅仅在原空间上,做数据搬移就能实现这个愿望呢?答案是有的。

         那么我们要发出的一个很自然的问题是:什么时候我们进行这种搬移?

         当然是某一个奇数和它前面(左边)离他最远偶数之间,存在这种搬移。那么此时,很明显的需要两个索引来标识两个奇数和偶数。比如 上述序列:2 4 7 ,我们当然知道,正确的顺序是 7 2 4。那么我们应该怎么做呢?

    代码:

         我给出下面的核心代码,你大概就可以看懂了:

    1             tmp = array[j];//将奇数缓存起来
    2             for(int k = j;k>i;k--)
    3                 array[k] = array[k-1];
    4             array[i] = tmp;//将奇数放到它应该在的位置

    很明显,我们的做法是:将 7 缓存到一个变量中去,然后,将所有的偶数向后搬移一个单位,再将7放到它应该在的位置。上述代码就是解决这个问题的核心思路。

    但我在调试的过程中仍然遇到了数组越界这样的问题:

    我先把我的完整代码放在下面,以供参考:

     1 class Solution {
     2 public:
     3     void reOrderArray(vector<int> &array) {//tow pointer
     4          int length = array.size();
     5          int i = 0;//奇数索引位置
     6          int j = 0;
     7          int tmp;
     8         if(length > 1)
     9         {
    10         while((i < length) &&(j < length)) 
    11         {
    12             while((i< length) && (array[i]%2 == 1))
    13             {//找到第一个偶数
    14                 i++;
    15             }
    16             j = i+1;
    17             while((j< length) && (array[j]%2 == 0))
    18             {//找到第一个奇数
    19                 j++;
    20             }
    21             if((j == length) || (i == length)) 
    22                 break;
    23             tmp = array[j];//将奇数缓存起来
    24             for(int k = j;k>i;k--)
    25                 array[k] = array[k-1];
    26             array[i] = tmp;//将奇数放到它应该在的位置
    27         }
    28         }
    29     }
    30 };

    上述代码中,i和j就表示了双索引。在上述代码中,我多次将 i和j索引值与数组长度length作比较,目的就是为了防止越界。

    比如:开头的if(length > 1),则是为了说明这个数组至少有两个元素。下述的找到第一个奇数和第一个偶数,我们也加上 i < length和 j < length的限制。目的是为了避免越界,比如:加入数组为全奇数和或者全偶数的情况,必然会导致越界。

    总结:

    我在思考核心代码上画的时间并不是很多,但是在防止数组越界的问题折腾了很久,最终才提交上去,我想表明的观点是:

    • 凡是数组问题必然要考虑越界问题,及时进行边界约束。
    • 凡是数组问题,我们一定要考虑数组为空,数组中有一个元素,数组中有n个元素的情况
    • 凡是数组问题,双索引几乎成了一个必选的 解决思路。

    请记好上述三个凡是!!!

  • 相关阅读:
    java数据结构-循环链表实现
    java数据结构-普通链表实现测试
    java数据结构-普通链表实现
    java数据结构-排序算法-插入算法
    java数据结构-排序算法-快排算法
    java数据结构-递归算法-简单递归算法
    python------------------异常处理
    自定义Web框架
    Django框架第一篇
    Django框架之第二篇
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/12357206.html
Copyright © 2020-2023  润新知