今天,我们同事不知道从哪儿弄来一道有意思的题目,我做了觉得很有意思,而且这个算法运行速度也还过得去,个人觉得对算法的实践也相当有帮助,所以就写了以下内容来分享一下。
题目: 寻找这样一种数列,它仅仅能被2,3,5,7整除。请输出这样的数列。
问题的分析,一种是对每个数字进行遍历,这是一种很直觉的方法,从算法复杂度考虑,它耗费的时间必然是很大的。后来,我们想到问题可以转化为对2,3,5,7这些数据以及由它们组合(因式分解为2,3,5,7)的数据相乘得到。于是我按照这个想法写了以下的算法,算法中使用了有向双向队列(链表方式实现),作为数据的排序所用。
/*
the program cal 2,3,5,7
programer: jeyawn
finished date: 2008-5-21 23:30
*/
#include "stdafx.h"
#include <stdlib.h>
#include <memory.h>
#define MAX_LENGTH 4000
#define NULL ((void *)0)
typedef struct tagElem
{
unsigned long a;
unsigned long b;
struct tagElem *next;
struct tagElem *prev;
}Elem;
Elem *pHead = (Elem *)NULL;
Elem *pEnd = (Elem *)NULL;
long Length = 0;
/*basic op of list*/
void InQue(const Elem &e, unsigned long *pData)
{
Elem *pElem = new Elem;
memset(pElem, 0, sizeof(Elem));
pElem->a = e.a;
pElem->b = e.b;
Length++;
if (Length == 1)
{
pElem->next = (Elem *)NULL;
pElem->prev = (Elem *)NULL;
pHead = pElem;
pEnd = pElem;
}
else
{
Elem *pTmp = pEnd;
while (pTmp != NULL)
{
if (pData[pTmp->a] * pData[pTmp->b] > pData[e.a] * pData[e.b])
{
pTmp = pTmp->prev;
}
else
break;
}
if (pTmp != NULL)
{
pElem->next = pTmp->next;
if(pTmp->next)
pTmp->next->prev = pElem;
pElem->prev = pTmp;
pTmp->next = pElem;
}
else
{
pElem->prev = (Elem *)NULL;
pElem->next = pHead;
pHead->prev = pElem;
pHead = pElem;
}
if (pTmp == pEnd)
{
pEnd->next = pElem;
pElem->prev = pEnd;
pElem->next = (Elem *)NULL;
pEnd = pElem;
}
}
}
void OutQue()
{
if (Length > 0)
{
Elem *pElem = pHead;
pHead = pHead->next;
delete pElem;
if (Length == 1)
{
pHead = (Elem *)NULL;
pEnd = (Elem *)NULL;
}
else
{
pHead->prev = (Elem *)NULL;
}
Length--;
}
}
void PrintList(unsigned long *pData)
{
printf("/n");
Elem *pTmp = pHead;
while (pTmp!=NULL)
{
printf("[%d, %d] = [%d, %d]$$", pTmp->a, pTmp->b, pData[pTmp->a], pData[pTmp->b]);
pTmp = pTmp->next;
}
printf("/n");
}
#include <stdio.h>
void main()
{
unsigned long *pData = new unsigned long [MAX_LENGTH];
pData[0] = 2;
pData[1] = 3;
pData[2] = 4;
pData[3] = 5;
pData[4] = 6;
pData[5] = 7;
int Index0 = 6;
int Index1 = 0;
int Index2 = 2;
int Index3 = 1;
while (Index0 < MAX_LENGTH)
{
//printf("%d/n", Index0);
//PrintList(pData);
unsigned long result = pData[Index1] * pData[Index2];
// compare the list head and result and next data;
unsigned long next_data = pData[Index3] * pData[Index3];
//
if (result <= next_data)
{
if (Length > 0)
{
unsigned long list_head = pData[pHead->a] * pData[pHead->b];
unsigned long list_end = pData[pEnd->a] * pData[pEnd->b];
//
if (next_data <= list_end)
{
Elem e;
memset((Elem *)&e, 0, sizeof(Elem));
e.a = Index3;
e.b = Index3;
Index3++;
InQue(e, pData);
}
if (list_head > result)
{
if (pData[Index0 - 1] != result)
{
pData[Index0++] = result;
}
Index2++;
continue;
}
else if (list_head == result)
{
if (pData[Index0 - 1] != result)
{
pData[Index0++] = result;
}
Index2++;
continue;
}
else if (list_head < result)
{
Elem e;
e.a = Index1;
e.b = Index2;
InQue(e, pData);
Index1 = pHead->a;
Index2 = pHead->b;
OutQue();
continue;
}
}
else
{
if (result != pData[Index0 - 1])
{
pData[Index0++] = result;
}
Index2++;
continue;
}
}
else
{
Elem e;
memset((Elem *)&e, 0, sizeof(Elem));
e.a = Index1;
e.b = Index2;
InQue(e, pData);
if (Length > 0)
{
unsigned long list_head = pData[pHead->a] * pData[pHead->b];
unsigned long list_end = pData[pEnd->a] * pData[pEnd->b];
if (pData[Index3] * pData[Index3] <= list_head)
{
Index1 = Index3;
Index2 = Index3;
Index3++;
continue;
}
if (pData[Index3] * pData[Index3] <= list_end)
{
memset((Elem *)&e, 0, sizeof(Elem));
e.a = Index3;
e.b = Index3;
Index3++;
InQue(e, pData);
Index1 = pHead->a;
Index2 = pHead->b;
OutQue();
continue;
}
}
Index1 = Index3;
Index2 = Index3;
Index3++;
continue;
}
}
for (int i = 0; i < MAX_LENGTH; i++)
{
printf("%d ", pData[i]);
}
system("pause");
}