算法题3 寻找丑数&数值逼近

题目

只包含因子2、3、5的数字被称为丑数。例如4和6是丑数,而14不是丑数,因为含有因子7。习惯上把1作为第一个丑数。求按从小到大顺序的第1500个丑数。

分析

假设一个丑数顺序数组ugly_nums[],对于其中一个丑数ugly=ugly_nums[x],存在2*ugly_nums[i-1]<=ugly,2*ugly_nums[i]>ugly,也就是说2乘以一个丑数刚刚大于丑数ugly;

同理也存在3*ugly_nums[j-1]<=ugly,3*ugly_nums[j]>ugly,和5*ugly_nums[k-1]<=ugly,5*ugly_nums[k]>ugly。

那么第x+1个丑数应该是3个倍数结果中最小的那个,即ugly_nums[x+1]=min{2*ugly_nums[i],3*ugly_nums[j],5*ugly_nums[k]};

这应该算是一种数值逼近的思想,遇到一些需要计算的数值需找时可以考虑,比如找顺序数组中满足和为某值得数字对

算法需要借助一个辅助数组存储丑数,空间复杂度O(n)。时间复杂度O(n)

代码

 1 int FindUglyNum(unsigned int index)
 2 {
 3     int *uglynums=new int[index];
 4 
 5     uglynums[0]=1;
 6     uglynums[1]=2;
 7     uglynums[2]=3;
 8     uglynums[3]=4;
 9     uglynums[4]=5;
10 
11     unsigned int i=1,j=1,k=1;
12     unsigned int min_uglynum=0;
13     unsigned int idx=4;
14     while (idx<index)
15     {
16         if (2*uglynums[i]<uglynums[idx])
17         {
18             i++;
19         }
20         if (3*uglynums[j]<uglynums[idx])
21         {
22             j++;
23         }
24         if (5*uglynums[k]<uglynums[idx])
25         {
26             k++;
27         }
28         min_uglynum=MIN(MIN(2*uglynums[i],3*uglynums[j]),5*uglynums[k]);
29         uglynums[++idx]=min_uglynum;
30     }
31 
32     return uglynums[index-1];
33 }

 

数值逼近之和为n的连续整数序列

  输入一个整数,输出所有和为n的连续正数序列。例如:输入15,由于15=7+8=4+5+6=1+2+3+4+5,所以输出的序列为1,2,3,4,5;4,5,6;7,8

分析

  由于要求的子序列是连续的,那么就可以连续数字的相加一点一点逼近n。设small=big=1,sum=small+big,移动big并计算新sum=sum+big,直到sum>=n,如果sum=n,则small到big是所求的子序列之一,

  若sum>n,则调整small向后移动,直到sum<=n。循环依次调整big和small,直到small=n/2

代码

 1  void FindContinuousNumbers(int n)
 2  {
 3      int small = 1,big = 1;
 4      int middle = n/2;
 5      int sum = small;
 6 
 7      while(small <=middle&&big<=n)
 8      {
 9          sum += big;
10 
11          if(sum == n)
12          {
13              for(int i = small;i <= big;++i)
14                  cout<<i<<" ";
15              cout<<endl;
16          }
17  
18          while(sum > n)
19          {
20              sum-=small;
21              small++;
22  
23              if(sum == n)
24              {
25                  for(int i = small;i <= big;++i)
26                      cout<<i<<" ";        
27                  cout<<endl;
28              }
29              
30          }
31          big++;
32      }
33  }

 

数值逼近之升序数组中和为n的数字对

  输入一个已经按升序排列的数组,一个给定的数字num,在数组中查找两个数,使得它们的和等于n。要求时间复杂度为O(n),如果存在多对满足条件的数字对,只给出一对即可

分析:

  既然是已经排列好的数组,又是求和,那么也可以用数值逼近的方式求解。设small=arr[0],big=arr[n-1],sum=small+big,若sum=num,则small和big就是要找的数对之一,若sum>num,则向前调整big,若sum<num,则向后调整small,直至small=big,循环结束。本题既然只要求给出一对数字,那么当sum=num时就可以停止查找了

代码 

 1  void FindSumPairs(int arr[],int len,int num)
 2  {
 3      if (arr==NULL||len<=0)
 4          throw std::exception("Invalid input.");
 5      int small=0,big=len-1;
 6      int sum=0;
 7 
 8      while (small<big)
 9      {
10          sum=arr[small]+arr[big];
11 
12          if (sum==num)
13              cout<<arr[small]<<' '<<arr[big]<<endl;
14 
15          if (sum>num)
16              big--;
17 
18          if (sum<num)
19              small++;
20      }
21 
22  }

 

    

转载于:https://www.cnblogs.com/wangzaizhen/p/5167015.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
王仁宏老师的《数值逼近》word文档,第一章 Weierstrass定理与线性算子逼近 §1Weierstrass第一定理 §2Weierstrass第二定理 §3线性正算子与Korovkin定理 第一章习第二章 一致逼近 §1Borel存在定理 §2最佳逼近定理 §3Tchebyshev最小零偏差多项式及其应用 §4最佳一致逼近的收敛速度估计 §5函数的构造性理论 §6代数多项式逼近理论中的有关结果 第二章习章 多项式插值方法 §1Lagrange插值公式 §2Newton插值公式 §3插值余项 §4有限差分计算 §5等距结点上的插值公式 §6Hermite插值公式 §7多元多项式插值 第章习第四章 平方逼近 §1最小二乘法 §2空间L  §3直交函数系与广义Fourier级数 §4直交函数结构公式 §5直交多项式的一般性质 §6直交多项式级数的收敛性 §7几种特殊的直交多项式 §8多元直交多项式 第四章习第五章 数值积分 §1数值积分的一般概念 §2Newton-Cotes公式 §3Romberg方法 §4Euler-Maclaurin公式 §5Gauss型求积公式 §6Gauss公式和Mehler公式 §7角精度与周期函数的求积公式 §8奇异积分的计算 §9高维求积公式 第五章习第六章 非线性逼近方法 §1非线性一致逼近 §2有理函数插值 §3Pade逼近方法 §4有理逼近的一些算法 §5Prony指数型函数逼近方法 第六章习第七章 样条逼近方法 §1样条函数及其基本性质 §2B-样条及其性质 §3次样条插值 §4多元样条 第七章习第八章 曲线、曲面生成与逼近 §1简单的数据处理方法 §2累加弦长法 §3Bezier方法 §4B-样条方法 §5非均匀有理B-样条(NURBS)  第八章习主要参考书目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值