和为S的两个数字VS和为s的连续正数序列

简介:

题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。

例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。

思路整理一下:最初我们找到数组的第一个数字和最后一个数字。首先定义两个指针,第一个指针指向数组的第一个(也就是最小的)数字,第二个指针指向数组的最后一个(也就是最大的)数字。当两个数字的和大于输入的数字时,把较大的数字往前移动;当两个数字的和小于数字时,把较小的数字往后移动;当相等时,打完收工。这样扫描的顺序是从数组的两端向数组的中间扫描。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool  FindNumbersWithSum( int  data[],  int  length,  int  sum,  int  *num1,  int  *num2)
{
     bool  found =  false ;
     if (length < 1 || num1 == NULL || num2 == NULL)
         return  false ;
     
     int  ahead = length - 1;
     int  behind = 0;
     
     while (ahead > behind)
     {
         long  long  curSum = data[ahead] + data[behind];
         if (curSum == sum)
         {
             *num1 = data[behind];
             *num2 = data[ahead];
             found =  true ;
             break ;
         }
         else  if (curSum > sum)
             ahead--;
         else
             behind++;
     }
     return  found;
}

 

 测试代码:

 

题目:输入一个正数S,打印出所有和为S的连续正数序列(至少有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5,4~6和7~8.

有了解决前面问题的经验,这里也考虑两个数small和big分别表示序列的最小值和最大值。

首先把small初始化为1,big初始化为2.如果从small到big的序列的和大于S,可以从序列中去掉较小的值,也就是增大small的值。

如果从small到big的序列的和小于S,可以增大big,让这个序列包含更多的数字。因为这个序列至少要有两个数字,我们一直增加small到(1+S)/2为止。

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

 

扩展:

2010年中兴面试题
编程求解:
输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<list> 
#include<iostream> 
using  namespace  std; 
   
list< int >list1; 
void  find_factor( int  sum,  int  n)  
     // 递归出口 
     if (n <= 0 || sum <= 0) 
         return
       
     // 输出找到的结果 
     if (sum == n) 
    
         // 反转list 
         list1.reverse(); 
         for (list< int >::iterator iter = list1.begin(); iter != list1.end(); iter++) 
             cout << *iter <<  " + "
         cout << n << endl; 
         list1.reverse();     
    
       
     list1.push_front(n);       //典型的01背包问题 
     find_factor(sum-n, n-1);    //放n,n-1个数填满sum-n 
     list1.pop_front(); 
     find_factor(sum, n-1);      //不放n,n-1个数填满sum  
   
int  main() 
     int  sum, n; 
     cout <<  "请输入你要等于多少的数值sum:"  << endl; 
     cin >> sum; 
     cout <<  "请输入你要从1.....n数列中取值的n:"  << endl; 
     cin >> n; 
     cout <<  "所有可能的序列,如下:"  << endl; 
     find_factor(sum,n); 
     return  0; 
}

 

 

 本文转自夏雪冬日博客园博客,原文链接:http://www.cnblogs.com/heyonggang/p/3642455.html,如需转载请自行联系原作者

目录
相关文章
|
算法 测试技术 C#
C++数位算法:数字1的个数
C++数位算法:数字1的个数
|
6月前
28.求任意一个整数的十位上的数字
28.求任意一个整数的十位上的数字
80 3
|
6月前
|
算法 测试技术 C++
【数位dp】【C++算法】600. 不含连续1的非负整数
【数位dp】【C++算法】600. 不含连续1的非负整数
|
6月前
|
机器学习/深度学习
【剑指offer】-和为S的连续正数序列-39/67
【剑指offer】-和为S的连续正数序列-39/67
剑指offer 64. 和为S的连续正数序列
剑指offer 64. 和为S的连续正数序列
64 0
面试题57 - II. 和为s的连续正数序列
面试题57 - II. 和为s的连续正数序列
面试题57 - II. 和为s的连续正数序列
|
机器学习/深度学习 算法
357. 统计各位数字都不同的数字个数 :「乘法原理」&「数位 DP」
357. 统计各位数字都不同的数字个数 :「乘法原理」&「数位 DP」