Skip to content

Algorithm - Sum 問題

2SUM 總和問題

雜湊表

public static int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> index = new HashMap<>();

    for (int i = 0; i < nums.length; i++) {
        index.put(nums[i], i);
    }

    for (int i = 0; i < nums.length; i++) {
        int other = target - nums[i];
        if (index.containsKey(other) && index.get(other) != i) {
            return new int[] { i, index.get(other) };
        }
    }

    return new int[] { -1, -1 };

}

雙指標 (單一解)

public static int[] twoSumI(int[] nums, int target) {

    int[] sortedNums = Arrays.copyOf(nums, nums.length);

    Arrays.sort(sortedNums);

    int left = 0, right = sortedNums.length - 1;

    while (left < right) {
        int sum = sortedNums[left] + sortedNums[right];

        if (sum == target) {
            int index1 = -1, index2 = -1;
            for (int i = 0; i < nums.length; i++) {
                if (nums[i] == sortedNums[left] && index1 == -1) {
                    index1 = i;
                } else if (nums[i] == sortedNums[right]) {
                    index2 = i;
                }
            }
            return new int[] { index1, index2 };
        } else if (sum < target) {
            left++;
        } else if (sum > target) {
            right--;
        }
    }

    return new int[] { -1, -1 };
}

public static void main(String[] args) {
    int target = 6;
    int[] nums = new int[] { 3, 1, 3, 5 };
    int[] res = twoSumI(nums, target);
    System.out.printf("%d[%d] + %d[%d] = %d", nums[res[0]], res[0], nums[res[1]], res[1], target);
}

雙指標 (所有解)

public static List<int[]> twoSumII(int[] nums, int target) {

    // 紀錄原始陣列的值與索引位置
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }

    // 複製一份原始陣列,並且排序,以進行雙指標演算法
    int[] sortedNums = Arrays.copyOf(nums, nums.length);
    Arrays.sort(sortedNums);

    List<int[]> res = new ArrayList<int[]>();

    int left = 0, right = sortedNums.length - 1;

    while (left < right) {
        int leftVal = sortedNums[left];
        int rightVal = sortedNums[right];
        int sum = leftVal + rightVal;
        if (sum == target) {

            int index1 = map.get(leftVal);
            int index2 = map.get(rightVal);

            res.add(new int[] { index1, index2 });

            // 跳過重複的作法
            while (left < right && sortedNums[left] == leftVal)
                left++;
            while (left < right && sortedNums[right] == rightVal)
                right--;

        } else if (sum < target) {
            while (left < right && sortedNums[left] == leftVal)
                left++;
        } else if (sum > target) {
            while (left < right && sortedNums[right] == rightVal)
                right--;
        }
    }
    return res;
}

public static void main(String[] args) {
    int target = 4;
    int[] nums = new int[] { 1, 1, 1, 2, 2, 3, 3 };
    List<int[]> resList = twoSumII(nums, target);
    for (int[] res : resList)
        System.out.printf("%d[%d] + %d[%d] = %d\n", nums[res[0]], res[0], nums[res[1]], res[1], target);
}

3SUM 總和問題

(待續)