算法:把数组中的 0 移动到最后-双指针思想

题目

把数组中的 0 移动到最后,其他数字顺序不变,(必须在原数组上操作)例如:

[1, 0, 3, 4, 0, 0, 11, 0]

变为

[1, 3, 4, 11, 0, 0, 0, 0]

双循环

/**
 * 移动 0 到数组的末尾(嵌套循环)
 * @param arr number arr
 */
export function moveZero1(arr: number[]): void {
    
    
    const length = arr.length
    if (length === 0) return

    let zeroLength = 0

    // O(n^2)
    for (let i = 0; i < length - zeroLength; i++) {
    
    
        if (arr[i] === 0) {
    
    
            arr.push(0)
            arr.splice(i, 1) // 本身就有 O(n)
            i-- // 数组截取了一个元素,i 要递减,否则连续 0 就会有错误
            zeroLength++ // 累加 0 的长度
        }
    }
}
// 功能测试
const arr = [1, 0, 3, 4, 0, 0, 11, 0]
moveZero2(arr)
console.log(arr)

双指针思想

  • 定义 j 指向第一个 0,i 指向 j 后面的第一个非 0。
  • 交换 i 和 j 的值,继续向后移动

只遍历一次,所以时间复杂的是 O(n)

/**
 * 移动 0 到数组末尾(双指针)
 * @param arr number arr
 */
export function moveZero2(arr: number[]): void {
    
    
    const length = arr.length
    if (length === 0) return

    let i
    let j = -1 // 指向第一个 0

    for (i = 0; i < length; i++) {
    
    
        if (arr[i] === 0) {
    
    
            // 第一个 0
            if (j < 0) {
    
    
                j = i
            }
        }

        if (arr[i] !== 0 && j >= 0) {
    
    
            // 交换
            const n = arr[i]
            arr[i] = arr[j]
            arr[j] = n

            j++
        }
    }
}

总结

遇到双循环的情况,就想双指针。

猜你喜欢

转载自blog.csdn.net/weixin_43972437/article/details/130331731