问答题
已知长度为n(n>1)的单链表,表头指针为L,结点结构由data和next两个域构成,其中data域为字符型。试设计一个在时间和空间两方面都尽可能高效的算法,判断该单链表是否中心对称(例如xyx、xxyyxx都是中心对称的),要求:
问答题
给出算法的基本设计思想。
【正确答案】
【答案解析】算法的基本设计思想:
①借助辅助栈,将链表的前一半元素依次进栈。注意即为奇数时要特殊处理。
②在处理链表的后一半元素时,当访问到链表的一个元素后,就从栈中弹出一个元素,两元素比较,若相等,则将链表中下一元素与栈中再弹出元素比较,直至链表到尾。
③若栈是空栈,则得出链表中心对称的结论;否则,当链表中一元素与栈中弹出元素不等时,结论为链表非中心对称。
问答题
根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
【正确答案】
【答案解析】算法的实现如下:
typedef struct LNode{ //链表结点的结构定义
char data; //结点数据
struct LNode *next; //结点链接指针
} *LinkList;
int Str_Sym(LinkList L, int n){
//本算法判断带头结点的单链表是否是中心对称
Stack s; initstack(s); //初始化栈
LNode *q, *p=L->next; //q指向出栈元素,P工作指针
for(int i=1; i<=n/2; i++){ //前一半结点入栈
push(p);
p=p->next;
}
if(n%2==1) p=p->next; //若n为奇数,需要特殊处理
while(p!=null){ //后一半表依次和前一半表比较
q=pop(s); //出栈一个结点
if(q->data==p->data) p=p->next; //相等则继续比较下一个结点
else break; //不等则跳出循环
}
if(empty(s)) return 1; //栈空,则说明对称
else return 0; //否则不对称
}
问答题
说明你所设计算法的时间复杂度和空间复杂度。
【正确答案】
【答案解析】算法的时间复杂度为O(n),空间复杂度为O(n)。
思考:若当长度未知时,该如何操作比较方便?
这里给出两种参考方法:
①先用遍历一遍链表数出元素个数再按参考答案操作。
②同时设立一个栈和一个队列,直接遍历一边链表把每个元素的值都入栈、入队列,然后再一一出栈、出队列比较元素的值是否相同。
[解析] 思路1(借助栈,空间复杂度高):将表的前半部分依次进栈,依次访问后半部分时,从栈中弹出一个元素,进行比较。思路2(类似折纸的思想,算法复杂):找到中间位置的元素,将后半部分的链表就地逆置,然后前半部分从前往后、后半部分从后往前比较,比较结束后再恢复(题中没有说不能改变链,故可不恢复)。
为了让算法更简单,这里采用思路1,思路2中的方法留给有兴趣的读者。