日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构与算法--有序数组中找出和为s的两个数字

發布時間:2023/12/4 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法--有序数组中找出和为s的两个数字 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有序數組中找和為s的兩個數字

題目:輸入一個遞增排序的數組array, 和一個數字s, 在數組中找出兩個數,使得這兩個數的和是s,如果有多對,輸出一對即可。
最簡單方案
  • 雙循環,每次獲取一個數據,和數組中其他數據求和,與s比較,此方法最直觀,時間復雜度是O(n2),比如必然會有更優解
優化方案一
  • 既然要找兩個數字,而且是數組,第一感覺就是雙指針的策略,分析如下

    • 既然要找兩個數字,那么假如我們隨機選兩個,如果和小于s,那么應該向后找,反之向前找
    • 案例分析法{1,2,4,7,11,15},找和為15 的
    • 初始化兩個指針分別指向 最后元素positionBig,指向第一個元素 positionSmall
    • 如果兩個數據和正好是s,那么得到解
    • 如果兩個數據和大于s,說明需要減少,那么應該positionBig –
    • 如果兩個數據和小于s,說明需要增大,那么應該positionSmall++
    • 如下圖:
  • 如上分析有如下代碼

/*** 在有序數組中查找和為 s的兩個數字* @author liaojiamin* @Date:Created in 17:38 2021/6/29*/ public class FindSumInSortArray {public static void main(String[] args) {int[] array = new int[]{1,2,3,7,8,11,14,16,17,18,23,47,59,67,79,83,222,344,556,778};System.out.println(findSumNum(array, 111));}/*** 找出遞增排序數組中的兩個數字,使得這兩個數字的和為 s* */public static boolean findSumNum(int[] array, int s){if(array == null || array.length <= 0){return false;}int positionBig = array.length -1;int positionSmall = 0;while (array[positionBig] + array[positionSmall] != s){if(positionBig < positionSmall){return false;}if(array[positionBig] + array[positionSmall] > s){positionBig --;}if(array[positionBig] + array[positionSmall] < s){positionSmall++;}}System.out.println(array[positionSmall] + " + "+ array[positionBig] +" = "+ s);return true;} }
  • 如上代碼中我們while循環的退出條件是 positionBig< positionSmall那么我們總共應該就是一次循環,時間福再度是O(n),不使用額外空間

變種題型,非有序數組

題目:輸入一個非有序數組array, 和一個數字s, 在數組中找出兩個數的組合,使得這兩個數的和是s,如果有多對,輸出多對即可。
  • 因為沒有了有序的特性,我們無法用上題中的方案,最簡單辦法,先排序,在按上面的方法,這樣時間復雜度比如超過O(n)
  • 另一中思路,空間換時間:
    • 遍歷數組,并且將數組已經遍歷過的值k 存儲在hash中,存儲模式為 key = k, value = k,這樣可以用O(1)的時間拿到已經范問過的數據
    • 每次遍歷數組中數據 n 時候,查找hash中 s-n
    • 如果s-n 存在,那么在之前遍歷過的數據中存在與n 配對后和為s的數據,一次遍歷完數據,找到我們需要的所有配對:
/*** 非有序數組中找出和為s的兩個數* */public static boolean findSumInList(int[] array, int s){if(array == null || array.length <= 0){return false;}boolean exists = false;Map<Integer, Integer> sumKeyValue = new HashMap<>();for (int i = 0; i < array.length; i++) {Integer key = array[i];if(sumKeyValue.containsKey(s - key)){System.out.println(key +" + "+ (s-key) +" = "+ s);exists = true;}sumKeyValue.put(key, key);}return exists;}
  • 以上解法借助了HashMap,所以在時間復雜度計算中需要考慮containsKey的開銷,如果出題人不讓用jdk相關的集合類,我們可以通過數組自己實現一個Hash。

更復雜的題型

類似題:輸入一個正數s,打印所有 和 為s的連續正數序列(至少含有2個數字),例如,輸入15,得到1+2+3+4+5 = 4+5+6=7+8,所以我們有打印出三個連續的序列1 ~ 5, 4 ~ 6, 7 ~ 8
  • 按如上題目的解決思路,此處也是尋找和為s的值,只不過是N數據的和,并且沒有給出數字,那么案例中s=15,時候其實隱含的條件就是數組是 1~14 ,因為條件中都是正整數,那么有如下分析:

    • 依然雙指針方法,因為此處我們需要找連續的數據,那么不能前后尋找,設positionBig = array.length,positionSmall = pogitionBig-1
    • 如果positionSmall ~ positionBig 中所有數據和 為 s,那么得出正解,此時讓positionBig–,positionSmall = positionBig-1,繼續求解
    • 如果positionSmall ~ positionBig中所有數據和 > s,那么說明數據和過大,我們應該減少大的值positionBig–
    • 如果positionSmall ~ positionBig 中所有數據和 < s, 說明數據和 過小,我們擴大數據的基數,讓更多數據累加 positionSmall –
    • 我們從后向前逐個逐個的查詢求和的組合,最后得到正解
    • 如下圖所示:
  • 第一個數列:

  • 第二個數列:

  • 第三個數列:

  • 經如上分析有如下代碼:

/*** 在有序數組中查找和為 s的兩個數字* @author liaojiamin* @Date:Created in 17:38 2021/6/29*/ public class FindSumInSortArray {public static void main(String[] args) {int[] arrayAll = new int[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14};System.out.println(findAllSumList(arrayAll, 15));}public static boolean findAllSumList(int[] array, int s){if(array == null || array.length <= 0){return false;}boolean exists = false;int positionBig = array.length -1;int positionSmall = 0;while (array[positionBig] > s){positionBig --;}positionSmall = positionBig-1;while (positionBig > 0){Integer sum = 0;for (int i = positionSmall; i <= positionBig; i++) {sum+=array[i];}if(sum == s){System.out.println(array[positionSmall] + " ~ "+ array[positionBig] +" = "+ s);exists = true;positionBig--;positionSmall = positionBig-1;continue;}if(sum < s){positionSmall--;if(positionSmall < 0){return exists;}continue;}if(sum > s){positionBig --;continue;}}return exists;} }
  • 如上實現代碼中我用雙指針的方式來做了一個類似雙循環的操作,每次找到解,則遞減一位,讓標記為從一個方向遍歷整個數組,時間復雜度O(n2)。
變種題型: 輸入一個正數s,打印所有 和 為s的元素的組合(至少含有1個數字),例如,輸入{1,2,3,4,5,6,7,8,9,10,11,12,13,14},9,得到如下
9 8,1 7,2 6,3 6,2,1 5,4 5,3,1 4,3,2
  • 解題分析:

    • 如上案例分析中,存在不很多不連續的數列也可以符合組合求和的題目要求,因此連續查找的方式需要進行調整
    • 還是延續上題中思路,找到第一個小于目標值的positionBig, 令positionSmall = positiomBig - 1
    • 依次遍歷positionSmall ~ 0 ,并在臨時數組temp 保存positionBig值
    • 令sum = positionSmall + sum(temp),
    • 當sum > s,說明當前數據過大,需要減小,執行positionSmall –
    • 當sum < s ,說明當前數據過小,但是可能符合要求,將positionSmall 添加到temp,執行positionSmall –
    • 當sum = s ,符合題解,將當前temp 添加到resultList隊列中得到一組解,并且執行positionSmall –
    • 依次執行如上流程,直到positionSmall < 0,執行positionBig –
    • 查找退出條件 positionBig < 0
  • 經如上分析有如下代碼:

/*** 在有序數組中查找和為 s的數字的所有組合情況* @author liaojiamin* @Date:Created in 17:38 2021/6/29*/ public class FindSumInSortArray {public static void main(String[] args) {int[] arrayAll = new int[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14};List<int[]> allCombom = findAllCombination(arrayAll, 9);for (int[] mySumNum : allCombom) {for (int i = 0; i < mySumNum.length; i++) {if(mySumNum[i] > 0){System.out.print(mySumNum[i] + ",");}}System.out.println();}}/*** 有序數組中找出所有和為s的數字的組合,* */public static List<int[]> findAllCombination(int[] array, int s){if(array == null || array.length <= 0){return Lists.newArrayList();}int positionBig = array.length - 1;List<int[]> allCombination = new ArrayList<>();while (array[positionBig] >= s){if(array[positionBig] == s){allCombination.add(new int[]{array[positionBig]});}positionBig--;}while (positionBig > 0){int positionSmall = positionBig - 1;int[] temp = new int[positionBig+1];temp[0] = array[positionBig];int tempPosition = 1;while (positionSmall >= 0){int sum = 0;for (int i=0;i<temp.length;i++){sum+=temp[i];}sum += array[positionSmall];if(sum > s){positionSmall --;continue;}if(sum < s){temp[tempPosition] = array[positionSmall];tempPosition ++;positionSmall--;continue;}if(sum == s){temp[tempPosition] = array[positionSmall];allCombination.add(temp);temp = new int[positionBig];tempPosition = 0;temp[tempPosition] = array[positionBig];tempPosition ++;positionSmall --;continue;}}positionBig --;}return allCombination;} }

上一篇:數據結構與算法–數組中出一次的數字
下一篇:數據結構與算法–翻轉單詞順序

總結

以上是生活随笔為你收集整理的数据结构与算法--有序数组中找出和为s的两个数字的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。