1.设计一个时间复杂度为O(n)的算法,实现将数组A[n]中所有元素循环右移k个位置
举例:a[] = {1,2,3,4,5},循环右移1位后 a[] = {5,1,2,3,4};
首先,我们可能想到的算法是,先将数组的后k个元素保存到一个临时数组中,然后将前n-k个元素右移k个位置.然后将临时数组的元素复制到元素的前k个位置.
实现:
template
void MoveArrayAdditional(T array[], int nLen, int k)
{
// 后k个元素移到临时数组,然后将前n-k个元素循环右移k位,再将临时数组元素放到数组前面
int other[k];
int m = k;
for (int i = 0; i
这个算法的时间复杂度符合要求,但是需要额外的k个存储单元.
我们可以换个角度解决这个问题.把这个问题看作把数组ab转换为数组ba;先将a逆置得到a^b,再将b逆置得到a^b^,最后将这个a^b^逆置得到(a^b^)^ = ba.于是得到:
template
void MoveArray(T array[], int nStart, int nEnd)
{
while (nStart < nEnd)
{
T temp = array[nStart];
array[nStart] = array[nEnd];
array[nEnd] = temp;
nStart++;
nEnd--;
}
}
emplate
void MoveArrayK(T array[], int nLen, int k)
{
MoveArray(array, 0, nLen-1);
MoveArray(array, 0, k-1);
MoveArray(array, k, nLen-1);
}
可以用翻转左右手来形象的形容这个问题.
2.已知数组A[n]的元素为整型,设计算法将其调整为左右两部分,左边所有元素为奇数,右边所有元素为偶数.
void DevisionOddAndEven(int array[], int nLen)
{
// 设置两个标志位,分别指示数组头和尾;
// 判断头元素是否为奇数
// 是:组头标记前移;
// 不是:将头元素与尾元素互换,尾元素前移.
// 当头元素和尾元素标记重合,停止
int nStart = 0;
int nEnd = nLen - 1;
while (nStart != nEnd)
{
if (array[nStart]%2 != 0)
{
nStart++;
}else
{
int temp = array[nStart];
array[nStart] = array[nEnd];
array[nEnd] = temp;
nEnd--;
}
}
}
3.给定两个链表的头结点,判断是否相交
template
bool TwoLinkIsIntersect(Node* pHead1, Node* pHead2)
{
if (pHead1 == NULL || pHead2 == NULL)
{
return false;
}
// 1.两个链表相交,它们的尾结点一定相同;所以分别找到两个链表的尾结点,判断值是否相等.
Node* rear1 = pHead1;
Node* rear2 = pHead2;
while (rear1->pNextNode != NULL || rear2->pNextNode != NULL)
{
if (rear1->pNextNode != NULL)
{
rear1 = rear1->pNextNode;
}
if (rear2->pNextNode != NULL)
{
rear2 = rear2->pNextNode;
}
}
if (*rear1 == *rear2)
{
return true;
}
return false;
}