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

简介: 题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。

 

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

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

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

 

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;
}

 

 测试代码:

#include<iostream>
using namespace std;

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;
}

int main()
{
    int data[] = {1, 2, 4, 7, 11, 15};
    int length  = sizeof(data) / sizeof(int);
    
    int num1, num2;
    bool result = FindNumbersWithSum(data, length, 15, &num1, &num2);
    if(result)
    {
        cout<<"num1:"<<num1<<endl;
        cout<<"num2:"<<num2<<endl;
    }
    else
        cout<<"failed!"<<endl;
    
    return 0;
}

 

题目:输入一个正数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为止。

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 ,要求将其中所有的可能组合列出来。

 

#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;  
}

 

 

 

 

 

img_e00999465d1c2c1b02df587a3ec9c13d.jpg
微信公众号: 猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

相关文章
|
JavaScript Java 关系型数据库
Springboot+vue的应急救援物资管理系统,Javaee项目,springboot vue前后端分离项目。
Springboot+vue的应急救援物资管理系统,Javaee项目,springboot vue前后端分离项目。
|
人工智能 Cloud Native 数据库
“云+AI”浪潮下,阿里云&龙蜥携手打造智算时代最佳服务器操作系统
AI 时代的来临,也推动着云计算发展迎来第三次浪潮。
|
移动开发 前端开发 定位技术
分享107个PHP源码,总有一款适合您
分享107个PHP源码,总有一款适合您
244 0
|
安全 Windows
小白学习Cobalt Strike4.5(二)
小白学习Cobalt Strike4.5(二)
476 0
小白学习Cobalt Strike4.5(二)
|
存储 缓存 算法
三种常用的数据分片方式:Hash分片,一致性Hash分片和按照数据范围分片
三种常用的数据分片方式:Hash分片,一致性Hash分片和按照数据范围分片
792 0
三种常用的数据分片方式:Hash分片,一致性Hash分片和按照数据范围分片
Visual Studio 2019 设置程序结束控制台不关闭
修改设置使控制台应用运行结束,控制台不自动退出。
940 0
Visual Studio 2019 设置程序结束控制台不关闭
|
数据可视化 数据挖掘
聚类分析 | MATLAB实现GMM高斯分布混合模型的聚类结果可视化
聚类分析 | MATLAB实现GMM高斯分布混合模型的聚类结果可视化
|
Android开发 Windows
|
消息中间件 数据可视化 Java
【SpringCloud-Alibaba系列教程】14.一文教你入门RocketMQ
本文将从入门到实战一文搞懂RocketMQ
1344 0
【SpringCloud-Alibaba系列教程】14.一文教你入门RocketMQ
|
编解码
MPEG中面向沉浸式视觉体验的标准化活动
业界对于HEVC的压缩性能比较认可,其实现复杂度也在不断地进行优化,但专利许可问题是HEVC在业界真正遇到的挑战。在HEVC编码专利许可问题的背景下,一些公司决定在MPEG国际标准组织以公开的方式来发展一个新的EVC标准。本文整理自浙江大学的虞露教授在LiveVideoStackCon 2019上海大会中的分享,详细介绍了近期在MPEG标准工作组中面向高沉浸感视觉体验而开展的一系列标准化活动。
543 0
MPEG中面向沉浸式视觉体验的标准化活动