pat1002

19 篇文章 0 订阅
16 篇文章 0 订阅

1002. A+B for Polynomials 

解题报告:


算法思想:
这道题目基于的思想就是多项式求和的方法,链表的插入、删除和排序操作。

数据结构:
定义一个由次幂和多项式系数组成的, 
struct node
{
    int b ;          //多项式的次幂数
    double a ; // 多项式的系数
} ;

根据定义的结构体,设定两个 node 类型的链表, list1 , list2 。



接收数据:
输入数据的格式是第一个数字代表的是后面的多项式系数非零的个数,用来控制循环接收{次幂和多项式系数}次数。



有两种求和思路,
 一个是使用基于归并排序的思想,分别对 list1 和 list2 进行按照元素多项式次幂(b) 非降序的排列,
然后分别访问 list1  list2 上节点多项式系数,进行比对加和处理,然后将结果存放到一个新的 list 中。
这种方法的时间复杂度可以这样来计算 m = list1.size() ; n = list2.size() ;  时间复杂度为 O( m+n) ,
但是空间复杂度较大 O(m+n) 因为需要一个额外的空间 list。

一个是基于链表插入合并的思想,首先也是对 list1 和 list2 进行按照节点多项式次幂 (b) 进行排序,然后遍历链表list2 中的各个节点,
在 list1中为 list2 中的节点找到合适的位置,将该节点插入至 list1 中
{
1. 合并 如果 list1[i].b == list2[i].b
 2 , 若在 list1 中没有找到任何节点的 b 值,即多项式系数数值相等,
则将 该 list2 中的节点安放到 list1 的尾部,最后进行一个排序操作即可为该插入节点放置到 list1 中的合适的位置上
 }
这种方法的时间复杂度是,O( m*n) , 因为对 list2 中的结点进行访问需要执行 n 次, 每访问 list2 中的一个节点都会对 list1 中的节点进行一次遍历。
所以一共会执行 m*n 次

需要注意的是,根据题意的要求,如果在多项式方程中系数为 0 的话是不会显示在输出数据中的, 所以在对系数加和之后还需要判断它的值是否为0 。
如果数值为 0  的话,是要将其从合并好的 list 中进行删除的,在这里使用的是 STL 中的 vector 来作为链表容器的, 删除其中多项式系数为 0 的方法
可以位于 vector 中最后的数值对 多项式系数为0 的节点中的各个属性进行覆盖,然后调用 vector 中的 pop_back , 将其最后的元素节点进行删除即可。

LZ在这里使用的是第二种方法,第一种方法还在调试。

#include <cstdio>
#include <algorithm>
#include <vector>
#include <math.h>

using namespace std ;

struct node
{
  double a ;
  int b ;

  node (double a , int b ) :a(a) , b(b ) {} 

  bool operator < (const node &n ) const
  {
    return b > n.b ;
  }
} ;

void  merge2 (  vector<node> &list1 ,  vector<node> list2 )
{
  vector<node> list ;
  vector<node>::iterator l1 = list1.begin() ;
  
    
  double sum = 0 ;

  
  for(int i = 0 ; i < list2.size() ;i++ )
  {
    l1 = list1.begin() ;

    while( l1!= list1.end() )
    {
      if(list2[i].b == l1->b )
      {
        break ;
      }
      else
        l1++ ;  
  
    }

    if(l1 == list1.end() ) //not find , no b matches ,push_back
      list1.push_back(node(list2[i].a , list2[i].b)) ;
    else //find , justice sum == 0?
    {
      
        l1->a += list2[i].a ;
    }


  }

  for(l1 = list1.begin() ; l1 != list1.end() ; l1++ )
  {
    if( l1->a == 0  )
    {
      break ;
    }
  }

  if(l1 != list1.end() ) // exist a = zero ,swap it to last one
  {
    l1->a = (list1.end()-1)->a ;
    l1->b = (list1.end()-1)->b ;

    list1.pop_back() ;
  }

  sort(list1.begin () , list1.end() ) ;

  
}



int main () 
{
  vector<node > list1 ;
  vector<node > list2 ;
  int b , len;
  double a ;

  
    scanf("%d", &len) ;
    for( int i = 0 ; i < len ; i++ )
    {
      scanf("%d%lf", &b , &a);

      list1.push_back( node ( a, b ) ) ;
    }
    
    scanf("%d", &len) ;
    for( int i = 0 ; i < len ; i++ )
    {
      scanf("%d%lf", &b , &a ) ;
      list2.push_back( node ( a , b ) ) ;
    }

    sort( list1.begin() , list1.end() ) ;
    sort ( list2.begin() , list2.end() ) ;

      merge2(list1 , list2 ) ;

      printf("%d ", list1.size() ) ;

    for(int i = 0 ; i < list1.size() ; i++)
    {
      printf("%d %.1f", list1[i].b , list1[i].a) ;
      if ( i != list1.size()-1 )
        printf(" ") ;
    }

	//system("pause") ;
    return 0 ;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值