【LeetCode(Java) - 259】較小的三數之和

學哥斌發表於2020-09-27

1、題目描述

在這裡插入圖片描述

2、解題思路

  先不考慮三個數字的問題,把問題變為:較小的兩個數之和,問題就簡單多了。

  首先對陣列進行排序,假如陣列為 nums = [3,5,2,8,1],找出和小於 7 的兩個數的組合數。

  排序後為 nums=[1,2,3,5,8];target = 7。

  定義兩個指標 left、right,初始時,left 指向 nums[0],right 指向最後一個元素;

  因為 nums[0] + nums[4] = 1 + 8 > 7,太大了,需要小一點,於是 right 往左走一步;

  接著 nums[0] + nums[3] = 1 + 5 = 6 < 7,符合要求,因此和小於 7 的組合數有 3 - 0 = 3 對。

  現在回到原題:求較小的三數之和的組合數。

  拿陣列的一個數,比如 nums[0] 當作其中一個數,於是 target 就變為 target - nums[0],問題就轉化為:從 nums[1] 到 nums[length-1] 中找到和小於 target - nums[0] 的兩個數的組合數。

  雙指標法的複雜度為 O(N),因為只遍歷一遍陣列。接著讓 nums 的每一個數字都當一次“其中一個數”,巢狀後,時間複雜度就為 O(N²)

3、解題程式碼

class Solution {
    public int threeSumSmaller(int[] nums, int target) {
        Arrays.sort(nums);
        int sum = 0;
        for (int i = 0; i < nums.length - 2; i++) {
            sum += twoSumSmaller(nums, i + 1, target - nums[i]);
        }
        return sum;
    }

    /**
     * 從 nums[] 的 startIndex 開始的元素中找到和小於 target 的兩個數的組合數
     * @param nums
     * @param startIndex
     * @param target
     * @return
     */
    private int twoSumSmaller(int[] nums, int startIndex, int target) {
        int sum = 0;
        int left = startIndex;
        int right = nums.length - 1;
        while (left < right) {
            if (nums[left] + nums[right] < target) {
                sum += right - left;
                left++;
            } else {
                right--;
            }
        }
        return sum;
    }
}

相關文章