个人评价:数组操作,尽量避免删除和插入操作,转换为值交换是个很好的优化手段~

题目难度:🌟🌟 (参考 LeeCode 简单🌟 、中等🌟 🌟 、困难🌟 🌟 🌟 )

另,通常算法题会考察分析时间复杂度和空间复杂度,可参考笔者之前的文章

「数据结构&算法」必知必会系列:3. 时间 & 空间复杂度(下)

调整数组顺序使奇数位于偶数前面

题目描述

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

示例:

输入:nums = [1,2,3,4]

输出:[1,3,2,4]

注:[3,1,2,4] 也是正确的答案之一。

提示:

0 <= nums.length <= 50000 1 <= nums[i] <= 10000

解题思路

方法一

此题保持空间复杂度O(1),直接在原数组上操作的方式不难。基础思路如下:

  • 遍历数组,找到偶数(如下标 i),将其移至数组尾(相当于删除 nums[i] 再插入该值)

较基础,代码就不放了。时间复杂度?🙌 O(n²)

显然,时间复杂度有待提升,那就再想想~

方法二

数组元素移动的操作会增加复杂度,如果可以直接交换值,只需常量 O(1) 的时间复杂度。

那如何进行合理的值交换呢?我们可以引入双指针,思路如下:

  • 从左向右的指针 i,如果找到偶数,停止
  • 从右至左的指针 j,如果找到奇数,停止
  • 两者进行交换,直至相遇(即 i<=j),完成整体置换

代码写法上各语言略有不同,但基本需要用到 continue 和 break,Go 代码参考如下:

func exchange(nums []int) []int {
    j := len(nums)-1
    for i := 0; i <= j ; i++ {
        if nums[i]%2 != 0 {
            continue
        }
        for j>i  {
            if nums[j]%2==1 {
                nums[j], nums[i] = nums[i], nums[j] //go 两数交换~
                break
            }
            j--
        }
    }
    return nums
}

不难,但是能信手拈来直接写出👆代码还是很能体现功力的~

总结

数组操作还是比较常用的,通常面试,只想到方法一是万万不够的。

个人认为此题很适合面试,循环的 break 和 continue 都用上了哈~