描述

在牛牛面前放着nn个数,这些数字既有奇数也有偶数,只不过牛牛对奇数情有独钟,他特别想让这些数都变成奇数。
现在牛牛获得了一种能力,他可以执行一种操作:每次选中一个偶数,然后把这些数中与该数相等的数都除以2,例如现在有一个数组为[2,2,3][2,2,3],那么牛牛可以执行一次操作,使得这个数组变为[1,1,3][1,1,3]。
牛牛现在想知道,对于任意的nn个数,他最少需要操作多少次,使得这些数都变成奇数?

示例1

输入:
3,[2,2,3]

返回值:
1

说明:
只需做一次操作,会将其中的偶数2都变成1,满足了所有的数都是奇数的要求。

示例2

输入:
3,[1,3,7]

返回值:
0

说明:
不需要做任何操作,因为所有的数原本就是奇数。

思路

这道题其实就是 找到所有的偶数,然后选中一个偶数除以 2, 并且相同的偶数都会执行除以2的操作。然后统计操作的次数。
其实咱们也不用非得所有数都除以2,每个数除以 2 之后给记录下来,以后碰到这个 数之后就跳过不用处理即可。

如上图:

  • 开始遍历数组,遇到第一个偶数先放入一个去重集合中,然后对该偶数除以2,如果还是偶数的话,在放入集合中在除以2,直到变为奇数为止。
  • 继续遍历数组,如果遇到偶数并且在集合中就跳过,否则继续执行上面操作。
  • 每次除以2时就将次数 + 1.

AC 代码

public int oddNumber (int n, int[] a) {
        // write code here
        if (a == null || a.length < 1) {
            return 0;
        }
        // 去重集合
        Set<Integer> set = new HashSet<>();
        // 总的次数
        int count = 0;
        // 遍历数组
        for (int i = 0; i < a.length; i ++) {
            // 如果时 偶数 并且不再集合中
            while ((a[i] & 1) == 0 && !set.contains(a[i])) {
                // 先加入去重集合
                set.add(a[i]);
                // 除以2
                a[i] /= 2;
                // 次数 ++
                count ++;
            }
        }
        return count;
    }
  • 时间复杂度:O(N), N 为数组长度,因为每个元素都要遍历一次。
  • 空间复杂度:O(N), 最坏的情况时每个元素都存储在集合中。

最后

大家有兴趣可以来我的牛客博客中看看其他内容,兴许对你有所帮助。