讀書筆記 算法 algorithms 第一章 2-sum 問題 3-sum 問題

3-sum

先說下 什麼是3-sum問題 :
舉例: 在N個數中找出三個和爲0 的整數.
最簡單的就是三重for循環 暴力求解. 這樣時間複雜度就是 $aN^3$ 立方級別 ,其中常數a取決於計算機的型號(性能).

2-sum

在解決3-sum問題之前 先看看2-sum問題 ,從簡單的開始. 2-sum 是什麼問題
舉例: 在N個數中找出兩個和爲0 的整數.
最簡單的解決辦法兩重for循環,暴力求解.這樣時間複雜度就是 $aN^2$. 平方級別.

歸併排序和二分查找

在解決2-sum之前先說下歸併排序和二分查找的問題規模和運行時間的關係.
歸併排序是線性對數級別 時間複雜度爲 $NlogN$, 二分查找是對數級別$logN$. 看圖

image
同樣分爲標準圖像和對數圖像.

解法

下面的解法是先採用歸併排序後再使用二分查找, 這樣他的運算時間和$NlogN$成正比.

歸併排序API

	Arrays.sort(a);

二分查找API

public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)

此方法傳入一個實現了Comparable接口的對象類的列表和要查找的元素。

使用二分搜索法搜索指定列表,以獲得指定對象。在進行此調用之前,必須根據列表元素的自然順序對列表進行升序排序(通過 sort(List) 方法)。 如果沒有對列表進行排序,則結果是不確定的。如果列表包含多個等於指定對象的元素,則無法保證找到的是哪一個。

如果搜索鍵包含在列表中,則返回搜索鍵的索引;否則返回 (-(插入點) - 1)。插入點 被定義爲將鍵插入列表的那一點:即第一個大於此鍵的元素索引;如果列表中的所有元素都小於指定的鍵,則爲 list.size()。注意,這保證了當且僅當此鍵被找到時,返回的值將 >= 0。

上代碼:

import java.util.Arrays;
import java.util.function.BinaryOperator;

public class Main {
	public static void main(String[] args) {
		int srcArray[] = { 32, 50, 64, 78, 81, 95, 101, 3, 5, 11, 17, 21, 23,
				28, 30, -81, -50 };
		System.out.println(count(srcArray));
	}

	public static int count(int[] a) {
		// 計算和爲0的整數對的數目
		Arrays.sort(a);
		int N = a.length;
		int cnt = 0;
		for (int i = 0; i < N; i++) {
			// 二分查找
			if (binSearch(-a[i], a) > i) {
				cnt++;
			}
		}

		return cnt;
	}

	public static int binSearch(int key, int srcArray[]) {
		int mid = srcArray.length / 2;
		if (key == srcArray[mid]) {
			return mid;
		}

		int start = 0;
		int end = srcArray.length - 1;
		while (start <= end) {
			mid = (end - start) / 2 + start;
			if (key < srcArray[mid]) {
				end = mid - 1;
			} else if (key > srcArray[mid]) {
				start = mid + 1;
			} else {
				return mid;
			}
		}
		return -1;
	}

}

打印: 2

3-sum 問題同理 多加一層循環即可

解析:
Arrays.sort(a); 歸併排序
binSearch(int key, int srcArray[]) 二分查找

PS 哈希表

上面的例子是書中爲了給讀者入門舉的例子, 實際上還可以使用哈希表方式.


public class Main {
	public static void main(String[] args) {
		int srcArray[] = { 32, 50, 64, 78, 81, 95, 101, 3, 5, 11, 17, 21, 23,
				28, 30, -81, -50 };
		System.out.println(hashMath(srcArray));
	}

	public static int hashMath(int[] a) {
		int count = 0;
		Map<Integer, Integer> map = new HashMap();
		for (int i = 0; i < a.length; i++) {
			int value = 0 - a[i];
			if (map.containsKey(value)) {
				count++;
			}
			map.put(a[i], i);
		}
		return count;
	}

結果: 2

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