7. 数组中只出现一次的数字
问题描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现了一次的数字。要求时间复杂度是 O(n)。空间复杂度是 O(1)。
例如:
输入数组 {2, 4, 3, 6, 3, 2, 5, 5},
输出 4 和 6
思路:
- 用位运算实现。任何一个数字异或它自己都等于零。如果将所有数字相异或,则最后的结果肯定是,那两个只出现一次的数字异或的结果。
所以:
根据异或的结果1所在的最低位,把数字分成两半,每一半里都还有只出现一次的数据和成对出现的数据。
这样继续对每一半相异或,则可以分别求出两个只出现一次的数字。
例如:
输入数组 {2, 4, 3, 6, 3, 2, 5, 5}。当依次对数组中的每个数字做异或运算之后,得到的结果用二进制表示是 0010。
异或得到的结果中,1 所在的最低位是倒数第二位。于是根据倒数第二位是不是 1,分为两个数组。
接下来分别对这两个子数组求异或。
代码:
|
|
8. 数组中重复的数字
问题描述:
在一个长度为 n 的数组里,所有的数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不值得每个数字重复了多少次。
请找出数组中任意一个重复的数字。例如:如果输入长度为 7 的数组 {2, 3, 1, 0, 2, 5, 3}
那么对应的输出是重复的数字 2 或者 3。
思路:
注意到,数组长度为 n,数组中数字都在 0 到 n-1 范围内。
重排这个数组 array,从头到尾依次扫描。
当扫描到第 i 位时, 比较 array[i] 是否等于 i;
如果相等,接着扫描下一个数字;
如果不等,将 array[i] 与 第 array[i] 个数字比较。如果相等,就找到了一个重复的数字。如果不等,将 array[i] 与 第 array[i] 个数字互换位置;
这样 array[i] 就到了属于它的位置(值与下标相等)。然后重复这个比较、交换的过程。
代码:
|
|
分析:
代码中尽管有一个两重循环,但每个数字最多只要交换两次就能找到属于它自己的位置,因此总的时间复杂度是 O(n)。
所有的操作步骤都是在输入数组中进行的,不需要额外分配内存,因此空间复杂度是 O(1)。
9. 构建乘积数组
问题描述:
给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B 中的元素 B[i] = A[0] A[1] … A[i-1] A[i+1] … A[n-1]。
不能使用除法。
思路:
- 计算数组 A 中,前 i-1 个元素的乘积,及后 n-i 个元素的乘积。这可以用动态规划实现;
- 计算 B[i] 的值。
|
|