面試之求找兩個數和為某個數、幾個連續數等於某個數


  問題1、輸入一個遞增排序數組和一個數字s,在數組中查找兩個數,使得它們的和正好是s,如果有多對數字的和等於s,輸出任意一對即可。

  顯然,很快能想到的是使用蠻力法(O(n2)),先固定一個數字,再判斷剩下的n-1個數字與它的和是否等於s。這種效率顯然有點低,我們可以使用下面比較快的方式,時間復雜度O(n)。

  思路:我們通過兩個記錄數組的開始位置和結束位置,從數組的尾部開始,求兩個數字的和,

    如果兩個數的和大於我們需要求的數s,則后面的記錄前移一位(因為是排好序的,前移一位,相當於數值減少),再進行判斷,

    如果兩個數的和小於我們要求的數s,則前面的位置記錄后移一位(因為是排好序的,后移一位,相當於數值增加),再進行判斷,

    直至找到或者后面或前面的位置記錄重合。

代碼實現

/**
     * 輸入一個遞增排序數組和一個數字s,在數組中查找兩個數,使得它們的和正好是s,如果有多對數字的和等於s,輸出任意一對即可。因為java只能
     * 有一個返回值,這里返回了真假,或者可以改成數組,返回查找到的兩個數,這里就實現返回是否找到,如果找到就打印出來!
     * @param data 待查找的遞增數組
     * @param length 數組長度
     * @param sum 要查找的和
     * @return 是否查找成功!
     */
    public static boolean FindNumberWithSum(int data[],int length,int sum)
    {
        boolean found = false;
        if(length < 1)
        {    
            return found;
        }
        
        int ahead = length -1 ;  //較大數字的下標
        int behind = 0;  //較小數字的下標
        
        while(ahead > behind)
        {
            long curSum = data[ahead] + data[behind];
            
            if(curSum == sum)
            {
                System.out.println("查找成功!兩個數為:"+data[ahead]+"," + data[behind]);
                break;
            }
            else if(curSum > sum)
            {
                ahead -- ;
            }
            else
            {
                behind ++;
            }
        }
        return found;
    }

 

 

測試:

public static void main(String[] args)
    {
        int[] arr = {1,2,4,7,11,15};
        
        FindSumEqualNum.FindNumberWithSum(arr,arr.length,15);
    }

 

 

結果:

查找成功!兩個數為:11,4

 

 


 

問題2、輸入一個正數s,打印出所有和為s的連續正數序列(至少包含兩個數)。例如輸入15,由於1+2+3+4+5=4+5+6=7+8=15,所以打印出3個連續序列1~5、4~6、7~8

  同樣,使用蠻力法也可以解決該問題,即,從1開始,不斷往后累加,直到求的值等於或者小於累加值,相等代表找到,所求值 < 累加值 ,則證明沒找到, 累加初值加一,繼續計算。可見,這樣子會重復計算很多次中間的加法,我們可以通過下面的方式,較快速得出結果,盡量減少重復的累加。

  思路:使用兩個數small和big分別表示序列的最小值和最大值。首先把small初始化為1,big初始化為2,

     如果從small到big的序列的和大於s,我們可以從序列中減去較小的值,也就是增加small的值。

     如果從small到big的序列的和小於s,我們可以增大big讓這個序列包含更多的數字。

     因為序列至少有兩個數字,我們一直增加small到(1+s)/2為止

代碼實現

輸出查找到的連續數

/**
     * 輸出從數small到big之間的所有數
     * @param small 開始數【包含】
     * @param big  結束數【包含】
     */
    public static void PrintContinuousSequence(int small,int big)
    {
        for(int i = small ; i <= big ; i++)
        {
            System.out.print(i + ",");
        }
        System.out.println("");
    }

 

核心函數

    /**
     * 輸入一個正數s,打印出所有和為s的連續正數序列(至少包含兩個數)
     * @param sum 要求的連續的序列的和
     */
    public static void FindSeriousSequence(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;
            
        }
    }

 

 

測試

public static void main(String[] args)
    {
        FindSeriousSequence(15);
    }

 

 

結果:

1,2,3,4,5,
4,5,6,
7,8,

 

  感謝您的耐心查看!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM