题目来源: 计算机考研408真题2015年41题
题目描述:
- 描述: 41.(15分)用单链表保存m个整数,结点的结构为[data][link],且|data|≤n(n为正整数)。现 要求设计一个时间复杂度尽可能高效的算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点,例如,若给定的单链表HEAD如下:
要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C、C++或Java语言描述算法,关键之处给出注释.
3)说明你所设计算法的时间复杂度和空间复杂度。
思路:先序递归遍历
- 使用
辅助数组记录链表中已经出现的数值- 将数组所有元素初始化为0
- 将数值看作辅助数组的下标,数值出现一次,将数组中对应下标中存储的元素的大小+1
- 因为|data|≤n(n为正整数),所以数组的大小为n+1
- 遍历单链表每一个值的同时,对数组对应下标中存储的元素的大小进行检查,如果不是0,说明已经出现过,那么删除链表对应的结点
具体实现:
class My_Node{
int data;
My_Node link;
My_Node(int data,My_Node node){
this.data = data;
this.link = node;
}
void check(My_Node head,int n){ //方法
int[] arr = new int[n+1];
My_Node q,p = head;
while (p.link!=null){ //因为是带有头结点的链表
int number = Math.abs(p.link.data); //取绝对值
if(arr[number] == 0){ //检查该节点的值是否出现过
arr[number] = 1; //首次出现,则将数组对应下标的值赋为1
p = p.link; //将指针后移一位
}else{ //已经出现过,则删除该节点
q = p.link;
p.link = q.link;
}
}
}
void print(My_Node head){
while(head.link != null){
System.out.print(head.link.data+" ");
head = head.link;
}
}
}
public class day408_15 {
public static void main(String[] args) {
//创建一个单链表15->-7->15->15->21
My_Node head = new My_Node(Integer.MAX_VALUE,null);
int[] sample = {15,-7,15,15,21};
for(int i = 0;i < 5;i ++){
My_Node node = new My_Node(sample[i], null);
if(head.link!=null){
node.link = head.link;
head.link = node;
}else{
head.link = node;
}
}
//进行测试
head.print(head); //15->-7->15->15->21
head.check(head,21);
System.out.print("\n"+"进行删除操作后:");
head.print(head); //15->-7->21
}
}
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情”