12~15年408算法

一.2012

 遇到的问题:1.两个链表的长度不同时,遍历的位置不同步

算法思路:1.求出两个链表的长度m和n

                  2.让p,q分别指向两个链表的头结点,如果m>n则让p移动到m-n+1的位置;如果m<n则让q移动到m-n+1的位置,这样两个指针的移动就可以同步了。

                  3.反复让p,q指针同步往后移动,并判断是否指向同一结点,若是,则该结点就是两个链表的共同后缀起始位置。

                  4.时间复杂度:o(m+n)

//求解链表长度
int  length(Linklist  L){
    int i=0;
    LNode  *p = L->next;
    while(p!=NULL){
     p=p->next
     ++i;
   }
   return i;
}

//查找位置
Linklist  find(Linklist  str1,Linklist str2){
   int  len1=length(str1), len2=length(str2);
   LNode  *p,*q;

  //使链表等长
   for(p=str1; len1>len2; len1--)  
       p=p->next;
   for(q=str2; len1<len2; len2--)
       q=q->next;

  //注意此时p,q后面的长度相等,所以p不空则q不空
   while(p->next!=NULL && p-next !=q->next){
      //两指针同步后移
        p=p->next;
        q=q->next;
}

}

二.2013

 1.暴力解法(虚拟数组)10分

 注意:0<=元素<n

思路:1.用虚拟数组表示A中元素出现的次数,比如A数组:0       1       2         3

                                                                                       值:2      3        2         1

                                                                         则虚拟数组 :0       1       2         3

                                                                值(表示个数):  0       1        2       1

          2.观察虚拟数组中的值是否大于n/2

//int   find(Sqlist &A)  //传顺序表不用定义n,长度直接A.length,元素用A.data[i]

//传数组,n表示数组长度,元素A[i]
  int   find(A[],int n) {
  int   *B=(int *)malloc(sizeof(int)*n);
  int  max=0, p;  //p表示元素的位置
   for(int  i=0;i<n;++i){
      //虚拟数组初值赋0
      B[i]=0;
   }

  //遍历A数组,将元素个数存入B
   for(int j=0;j<n;++j){
       B[A[j]]++
  }

  //找B中元素最大值,再判断是否大于n/2
   for(int k=0;k<n;++k){//n表示数组长度,遍历数组
       if(max<B[K])   
        max=B[K];
        p=k;
  }
  //判断
     if(max>n/2)   return  p;//p代表数组B中的位置,B中的位置在A中表示元素值
     else   return  -1;

}

三.2014

注意:考察树和图一般比较简单(考递归比较多)

           1.只有叶子结点才有带权路径长度

            2.带权路径长度=左子树的+右子树的

            3.时间复杂度o(n)    空间复杂度o(n)-----递归用到栈

//定义树的结构体
typedef  struct BTNode{
     int  weight;
     struct   BTNode  *left,*right;
}BTNode;

int    fun(BTNode *root,int  deep){//要传深度

        int  A,B;
    //递归的一个出口(必须写)
     if (root==NULL)  return   0;

   //找叶子结点并求权重
     if(root->left==null && root->right==null)
         return   (root->weight)*deep;

   //左右子树递归
      A=fun(root->left,deep+1) //注意deep要加一
      B=fun(root->right,deep+1)

         return  A+B;

}
//主函数
void   main(BTNode  *root){
      int  fun(root,0); //给deep赋初值
}

四.2015

注意:1.出现“时间复杂度尽可能高效”,要考虑空间换时间(虚拟数组)

 1.暴力解

       重点:1.设置两个指针,两层循环  ;

                 2.删除结点的时候找到前一个结点指针  ;

                 3.一定要把 p->link !=NULL 放在外层循环,因为q是随着p而改变的

                 4. 时间复杂度o(n^2)    空间复杂度o(1)

//返回绝对值
int  ads(LNode *p){
   if(p->data >=0)   
       return  p->data;
    else
       return   -p->data;
}


//删除绝对值相同的元素
void   delete(LNode *&L){//链表改变了要加 &
     LNode *p=L; //把头结点赋给p

     while(p->link !=NULL){
          LNode  *q=p->link; //第一个结点赋给q
             while(q->link !=NULL){
                 //第一个结点等于第二个节点
                 if(abs(p->link) == abs(q->link)) {
                    LNode *r=q->link; //令r指向q后面的元素
                    q->link=r->link; 
                       free(r);
                   }else{   q->link;   }
                    
              }
           p=p->link;

       }
}

2.最优解(虚拟数组)

注意:1.data<=n ,所以数组的大小为n+1(数组从0开始)

           2.依次扫描单链表中的元素,对应值出现一次,则令值所对应位置上的元素为1,若第二次扫描到相同结点,会发现虚拟数组对应位置为1,则删除该链表元素。

           3.时间复杂度o(n)    空间复杂度o(n)

void  fun(LNode *L,int n){
     LNode  *p=L;
     int  m;
    int  *q=(int *)malloc(sizeof(int)*(n+1));
    for(int  i=o;i<n+1;i++) 
       q[i]=0;  //虚拟数组赋初值
 
   while(p->link !=NULL){
    m=p->link->data >0 ? p->link->data : -p->link->data;
       //首次出现
       if(q[m]==0)  {  q[m]=1;    p=p->link; }
          else{//删除
             LNode  *r=p->link;
              p->link=r->link;
               free(r);
           }
     }
   free(q);

}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值