zoukankan      html  css  js  c++  java
  • 和为S的两个数字VS和为s的连续正数序列

    题目:输入一个递增排序的数组和一个数字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("
    ");
    }
    

    扩展:

    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;  
    }
    
  • 相关阅读:
    kickstart自动安装部署RHEL7
    物流即使查询API
    快递单号查询快递鸟API接口-100家快递单轨迹推送
    物流跟踪API-快递单订阅
    如何最快实现物流即使查询功能-物流轨迹查询API
    提供一个不错的物流物流接口给大家,本人亲测,真的不错
    给idea添加类注释和方法注释模板
    分享一个生成反遗忘复习计划的java程序
    用TreeSet和Comparator给list集合元素去重
    对poi-excel导出的浅层理解
  • 原文地址:https://www.cnblogs.com/heyonggang/p/3642455.html
Copyright © 2011-2022 走看看