常用代碼模板1——基礎算法

將雪菜大佬的模板轉寫爲java形式,C++見大佬原文AcWing @yxc

快速冪算法模板

求 m*k%p,時間複雜度 O(logk)

int pow(int m, int k, int p) {
		int res = 1 % p;
		int t = m;
		while (k > 0) {
			if ((k & 1) == 1) {
				res = res * t % p;
			}
			t = t * t % p;
			k >>= 1;
		}
		return res;
	}

快速排序算法模板

	void quick_sort(int q[], int l, int r) {
		if (l >= r)
			return;

		int i = l - 1, j = r + 1, x = q[l + r >> 1];
		while (i < j) {
			do
				i++;
			while (q[i] < x);
			do
				j--;
			while (q[j] > x);
			if (i < j)
				swap(q, i, j);
		}
		quick_sort(q, l, j);
		quick_sort(q, j + 1, r);
	}

	void swap(int[] q, int i, int j) {
		int p;
		p = q[i];
		q[i] = q[j];
		q[j] = p;

	}

歸併排序算法模板

void merge_sort(int q[], int[] tmp, int l, int r) {
		if (l >= r)
			return;

		int mid = l + r >> 1;
		merge_sort(q, tmp, l, mid);
		merge_sort(q, tmp, mid + 1, r);

		int k = 0, i = l, j = mid + 1;
		while (i <= mid && j <= r)
			if (q[i] < q[j])
				tmp[k++] = q[i++];
			else
				tmp[k++] = q[j++];

		while (i <= mid)
			tmp[k++] = q[i++];
		while (j <= r)
			tmp[k++] = q[j++];

		for (i = l, j = 0; i <= r; i++, j++)
			q[i] = tmp[j];
	}

整數二分算法模板

boolean check(int x) {
		/* ... */ // 檢查x是否滿足某種性質
	} 

	// 區間[l, r]被劃分成[l, mid]和[mid + 1, r]時使用:
	int bsearch_1(int l, int r) {
		while (l < r) {
			int mid = l + r >> 1;
			if (check(mid))
				r = mid; // check()判斷mid是否滿足性質
			else
				l = mid + 1;
		}
		return l;
	}

	// 區間[l, r]被劃分成[l, mid - 1]和[mid, r]時使用:
	int bsearch_2(int l, int r) {
		while (l < r) {
			int mid = l + r + 1 >> 1;
			if (check(mid))
				l = mid;
			else
				r = mid - 1;
		}
		return l;
	}

浮點數二分算法模板


	boolean check(double x) {
		/* ... */ // 檢查x是否滿足某種性質
		} 

	double bsearch_3(double l, double r) {
		final double eps = 1e-6; // eps 表示精度,取決於題目對精度的要求
		while (r - l > eps) {
			double mid = (l + r) / 2;
			if (check(mid))
				r = mid;
			else
				l = mid;
		}
		return l;
	}

高精度算法

具體算法使用了快速傅里葉變換。 JAVA中有大整數類,可以直接使用,這裏不做轉譯。

二維前綴和

S[i, j] = 第i行j列格子左上部分所有元素的和
以(x1, y1)爲左上角,(x2, y2)爲右下角的子矩陣的和爲:
S[x2,y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]

一維差分

給區間[l, r]中的每個數加上c:B[l] += c, B[r + 1] -= c

二維差分

給以(x1, y1)爲左上角,(x2, y2)爲右下角的子矩陣中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1,y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c

位運算

求n的第k位數字: n >> k & 1
返回n的最後一位1:lowbit(n) = n & -n
使n的k位取反:n ^= (1 << k);
將n的k位設置爲x:if (x == 0) n &= ~(1 << k); else n |= (1 << k);

雙指針算法

for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具體問題的邏輯
}
常見問題分類:
    (1) 對於一個序列,用兩個指針維護一段區間
    (2) 對於兩個序列,維護某種次序,比如歸併排序中合併兩個有序序列的操作
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章