Java篇—和爲S的兩個數字

題目描述:

輸入一個遞增排序的數組和一個數字S,在數組中查找兩個數,使得它們的和正好是S,如果有多對數字的和等於S,輸出兩個數的乘積最小的那一對。

思路分析:

由於是遞增排序的數組,所以,我們可以使用兩個指針,分別指向數組的首元素和尾元素(一個從前往後,指向較小的數,一個從後往前,指向較大的數),這樣找到的兩個數的乘積必然是最小的。當兩個數的和大於S時,較大的數字指針向左移動,當兩個數的和小於S時,較小的數字指針向右移動,當兩個指針相遇時,查找結束。

代碼實現:

import java.util.ArrayList;
public class Exercise20 {
    public static void main(String[] args) {
        int[] array = {1,2,3,4,6,8,9,12};
        System.out.println(findNumbersWithSum(array,12));   //輸出結果  [3,9]
    }

    private static ArrayList<Integer> findNumbersWithSum(int[] array, int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        //如果原數組的長度小於2或者原數組爲空,直接返回list
        if(array.length < 2 || array == null){
            return list;
        }
        //定義兩個指針,分別指向數組的首元素和尾元素
        int low = 0;
        int high = array.length - 1;
        //對數組進行遍歷,當首尾指針相遇時結束,即low = high
        //讓兩個數字的位置不斷靠近
        while(low < high){
            if((array[low] + array[high] > sum)){
                //如果首尾元素的和大於sum,則尾指針減一,即 high--
                high--;
            }else if((array[low] + array[high] < sum)){
                //如果首尾元素的和小於sum,則首指針加一,即 low++
                low++;
            }else{
                //如果首尾元素的和等於sum,則把首尾元素加入到list集合中,最後返回即可
                list.add(array[low]);
                list.add(array[high]);
                return list;
            }
        }
        return list;
    }
}

解法2代碼實現及詳細註釋:

import java.util.ArrayList;
public class Exercise20 {
    public static void main(String[] args) {
        int[] array = {-2,-1,0,1,3,4};
        System.out.println(findNumbersWithSum1(array,1));   //輸出結果  [-2,3]
    }

    private static ArrayList<Integer> findNumbersWithSum1(int[] array, int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        //如果原數組的長度小於2或者原數組爲空,直接返回list
        if(array.length < 2 || array == null){
            return list;
        }

        /**
         * 定義兩個指針和i和j分別指向數組的第一個元素和第二個元素;
         * 外層循環控制第一個元素的位置,內層循環控制第二個元素的位置;
         * 如果 array[i] + array[j] = sum 並且list爲空,代表其是第一次放入,
         *           將p1和p2對應的值添加到list集合中,並且保存乘積max;
         * 如果 array[i] + array[j] = sum 並且list集合不爲空,代表其不是第一次放入,
         *       比較當前的兩個值和之前存入的兩個值乘積的大小,
         *       如果當前乘積小於之前保存的乘積,則重新創建一個list對象
         *       保存當前的兩個值,並使max = 當前兩個值的乘積
         * 最後返回list集合即可。
         */
        //max用來保存最大的乘積
        int max = 0;
        //i的取值範圍爲[0,array.length - 2],i不能指向數組的最後一個元素
        for (int i = 0; i < array.length - 1; i++) {
            //j的取值範圍爲[1,array.length - 1],j不能指向數組的第一個元素
            for (int j = 1; j < array.length; j++) {
                //如果兩者相加等於sum,並且list爲空,那麼代表其是第一次放入
                if((array[i] + array[j]) == sum && list.size() == 0){
                    list.add(array[i]);
                    list.add(array[j]);
                    //保存當前兩者的乘積
                    max = array[i] * array[j];
                }
                //如果兩者相加等於sum,並且list不爲空,那麼代表其不是第一次放入
                if((array[i] + array[j]) == sum && list.size() != 0){
                    //比較當前兩個數的乘積與第一次放入的兩個數乘積的大小
                    if((array[i] * array[j]) < max){
                        /**
                         * 如果當前i和j指針指向的兩個數的乘積小於max,重新new ArrayList一個對象
                         * 將其放入到list集合中,保存最大值即可
                         */
                        list = new ArrayList<>();
                        list.add(array[i]);
                        list.add(array[j]);
                        //保存當前兩者的乘積
                        max = array[i] * array[j];
                    }
                }
            }
        }
        return list;
    }
}

題目總結:

前者解法較爲靈活,巧妙的抓住了兩個數乘積最小的條件,定義首尾指針遍歷時第一次找到的兩個數即爲所求數。

例:[1,2,3,4]  sum = 5 ,1*4肯定小於2*3。

後者解法較爲複雜,但易於理解,把第一對元素之和等於sum的兩個數的乘積保存下來,與後面出現的每一對元素之和等於sum的兩個數的乘積作比較,將較小乘積的那兩個數放入到list集合中即可。

心靈雞湯:大腦的知識儲備從來不是空穴來風,既然不是天才,爲何不去努力?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章