数据结构与算法是计算机发展的基石,现代计算机的起源是数学,数学的核心是算法,计算机历史上每一次大的变革都离不开算法的推动。纵然“条条大路通罗马”,但好的算法永远比提高硬件设备管用。
如何判断一个数组中的数值是否是连续相邻
一个整数数列,元素取值可能是0-65535中的任意一个数,相同数值不会重复出现:0是例外,可以反复出现。设计一个算法,当从该数列中随意选取5个数值时,判断这5个数值是否连续相邻。需要注意以下4点:
(1)5个数值允许是乱序的,如 8 7 5 0 6。
(2)0可以通配任意数值,如 8 7 5 0 6 中的 0 可以通配成9 或者是 4.
(3) 0 可以多次出现
(4)全 0 算连续, 只有一个非 0 算连续。
解题思路:由题中的条件可以分两种情况讨论:
(1)如果没有 0 的存在,要组成连续的数列,最大值和最小值的差距必须是 4 ,存在 0 的最小值,时间复杂度为 O(n)。
(2)如果非 0 最大 - 非 0 最小 + 1 <=5 (即非0最大-非0最小 <=4)则这5个数值连续相邻。否则,不连续相邻。
因此,总体复杂度为O(n)。
所以,需要先遍历一遍数组,记录下5个数的最大值和最小值。然后,求最大值和最小值的差值。
找出数组中出现奇数次的元素
给定一个含有n个元素的整型数组array,其中只有一个元素出现奇数次,找出这个元素。
对于任意一个数k,有k^k = 0, k^0=k,所以将array中所有元素进行异或,那么个数为偶数的元素异或后都变成了0,只留下个数为奇数的那个元素。
引申:由n个元素组成的数组,n-2个数出现了偶数次,两个数出现了奇数次(这两个数不相等),如何用O(1)的空间复杂度,找出这两个数?
假设这两个数分为a、b,将数组中所有元素异或之后结果为 x,因为 a!=b,所以, x = a^b ,且 x!=0,判断x中位为1的位数,只需要知道某一个位为1的位数k,如 00101100,k可以取2或者3,或者5,然后将x与数组中第k位为1的数进行异或,异或结果就是a或b中的一个,然后用x异或,就可以求出另外一个。
因为x中第k位为1表示a或者b中有一个数的第k位也为1,假设为a,将x与数组中第k位为1的数进行异或时,也即将x与a以及其他第k位为1的出现过偶数次的数进行异或,化简即为x与a异或,最终结果即为b。
#include<iostream>
using namespace std;
void FindElement(int a[] , int length )
{
int s=0;
int i;
int k=0;
for( i=0; i<length; i++)
{
s = s^a[i];
}
int s1 = s;
int s2 = s;
while( !(s1&1) )
{
s1 = s1>>1;
k++;
}
for( i=0; i<length; i++ )
{
if( (a[i]>>k) & 1 )
s = s^a[i];
}
int p = s^s2 ;
cout << s << " " << p << endl;
}
int main()
{
int data[] = { 1,2,2,3,3,4,1,5 };
int len = sizeof( data )/sizeof( data[0] );
FindElement( data,len );
return