线性表专题3- 2020-4-8- 算法 04

235 阅读4分钟

线性表部分习题

关键字

  • 递增有序链表
  • 不允许有重复的数据
  • 保持递增关系(使用后插法)
  • 不占用额外的空间(额外的新建结点维持逻辑)

思路

  • a.待合并链表La,Lb,头指针Lc; 借用La的头结点
  • b.定义pa,pb指针
  • c.循环(La,Lb都没有达到尾结点的位置)
  • d.判断链表取较小者,存储Lc
  • e.相等La元素插入Lc,Lb释放掉

//Lc就是结果链表
void MergeList(LinkList *La,LinkList *Lb,LinkList *Lc){
    LinkList pa,pb,pc,temp;
    pa = (*La)->next;
    pb = (*Lb)->next;
    
    *Lc = *La;
    pc = *La;
    while(pa && pb){
        //1 d步骤
        if(pa->data < pb.data){
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }else if(pa->data > pb->data){
            pc->next = pb;
            pc = pb;
            pb = pb ->next;
        }else{ //e 步骤
            pc ->next = pa;
            pc = pa;
            temp = pb->next;
            free(pb);
            pb = temp;
        }
    }
    
    pc ->next = pa ? pa : pb ; //循环结束后 还有没遍历的 直接加到后面
    free(*Lb);
}

解析

  • 1.La,Lb,Lc(Lc指向La的头结点)
  • 2.pa,pb,首元结点
  • 3.循环条件 pa,pb不为空
  • 4.相等的话 La结点链接到Lc上 同时释放Lb结点
  • 5.较小的话 释放
  • 6.释放掉未走到的结点
void Intersection(LinkList *La,LinkList *Lb,LinkList *Lc){
    LinkList pa,pb,pc,temp;
    pa = (*La)->next;
    pb = (*Lb)->next;
    *Lc = pc = *La;
    while(pa && pb){
        if(pa->data == pb->data){
            pc->next = pa;
            pc = pa;
            pa = pa->next;
            
            temp = pb;
            pb = pb->next;
            free(temp);
        }else if(pa->data < pb->data){
            temp = pa;
            pa = pa->next;
            free(temp);
        }else{
            temp = pb;
            pb = pb->next;
            free(temp);
        }
    }
    while(pa){
        temp = pa;
        pa = pa->next;
        free(temp);
    }
    while(pb){
        temp = pb;
        pb = pb->next;
        free(temp);
    }
    pc->next = NULL;
}

关键词

  • 不能开辟新的空间
  • 只能改变指针的指向(头插法)

解析

  • a. *L 作为新的旋转后的链表的首节点
  • b. p指针指向首元结点
  • c. 从前往后遍历链表 临时变量q指向待插入结点的后继结点
    使用头插法
void Inverse(LinkList *L){
    LinkList p,q;
    p = (*L)->next;
    (*L)->next = NULL;
    while(p){
        q = p->next;
        p->next = (*L)->next;
        (*L)->next = p;
        p = q;
    }
}

关键词

  • a 遍历链表 第一个大于minK结点,pre 保存前驱
  • b 遍历链表 第一个大于maxK结点, p指向;
  • c 修改pre->next = p
  • d 释放介于pre和p之间的结点

解析

void DeleteMinMax(LinkList *L,int mink,int maxk){
    LinkList p,q,pre,temp;
    pre = *L;
    p = (*L)->next;
    while(p && p->data < mink){
        pre = p;
        p = p->next;
    }
    while(p && p->data <= maxk){
        p=p->next;
    }
    q = pre->next;
    pre->next = p;
    
    while(q !=p){
        temp = q->next;
        free(q);
        q = temp ;
    }
}

思路

  • a n个数据原地逆置 9 8 7 6 5 4 3 2 1 0
  • b 拆解【9 8 7 6 5 4 3】【2 1 0】
  • n-p个数据和p个数据再一次逆置 【3 4 5 6 7 8 9】【0 1 2】
void Reverse(int *pre,int left,int right){
    int i = left , j= right;
    int temp;
    while(i<j){
        temp = pre[i];
        pre[i] = pre[j];
        pre[j] = temp;
    
        i++;j--;
    }
    
}
void LeftShift(int *pre,int n,int p){
    if(p>0 && p<n){
        Reverse(pre,0,n-1);
        Reverse(pre,0,n-p-1);
        Reverse(pre,n-p,n-1);
    }
}

分析

  • 找主元素:数组中出现次数超过一般的元素

思路

  • 选择候选主元素,循环技术方式找到链表那个元素出现次数最多,认为候选人
  • 循环目的:候选人到底出现了多少次
  • 判断是不是候选人 count > n/2
int MainElement(int *A,int n){
    int count =1;
    int key = A[0];
    for(int i=1;i<n;i++){
        if(A[i]== key){
            count ++;        
        }else{
            if(count > 0 ){
                count --;
            }else{
               //更换候选人
                key = A[i];
                count = 1;
            }
        }
    }
    if(count > 0){
        for(int i= count=0;i<n;i++){
            if(A[i] == key){
                count++;
            }
        }
    }
    if(count > n/2){
        return key;
    }
    return -1;
}

关键词

  • 时间复杂度高效 可以用空间换时间

解析

  • 1 申请n+1个辅助空间数组t,赋初始值为0;
  • 2 首元结点开始遍历,t[|data|] 保留结点 t[|data|] = 1;若t[|data|] =1 就删除;

void DeleteEqualNode(LinkeList *L,int n){
    int *p = alloca(sizeof(int)*n);
    LinkList r = *L;
    for(int i= 0;i < n;i++){
        *(p+i) = 0;
    }
    LinkList temp = (*L)->next;
    while(temp != NULL){
        if(p[abs(temp->data)] == 1){
            r->next = temp ->next;
            free(temp);
            temp = r->next;
        }else{
            p[abs(temp->data)] = 1;
            r = temp;
            temp = temp->next;
        }
    }
    
}