給定三個整數數組
A = [A1, A2, ... AN],
B = [B1, B2, ... BN],
C = [C1, C2, ... CN],
請你統計有多少個三元組(i, j, k) 滿足:
1. 1 <= i, j, k <= N?
2. Ai < Bj < Ck?
【輸入格式】
第一行包含一個整數N。
第二行包含N個整數A1, A2, ... AN。
第三行包含N個整數B1, B2, ... BN。
第四行包含N個整數C1, C2, ... CN。
對于30%的數據,1 <= N <= 100?
對于60%的數據,1 <= N <= 1000
對于100%的數據,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000
【輸出格式】
一個整數表示答案
【輸入樣例】
3
1 1 1
2 2 2
3 3 3
【輸出樣例】
27
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗? < 1000ms
該題主要考查枚舉及對枚舉的優化,一點空間換時間的思維
枚舉:三重循環枚舉O(n^3),枚舉優化,先將給定三個數組排序,枚舉并記錄a數組中每個數,b數組大于該數的個數情況,同樣在枚舉b中每個數,c數組中大于該數的情況,對應乘積在求和即為所求(理解該處--原給定數組已排好序)O(n^2)
自己的理解:對于類似枚舉的算法題來說,最簡單的直接暴力枚舉是首先想到的,也是思路最簡單清晰的,當然不論是從題目實際考慮,還是對枚舉的經驗來說直接暴力枚舉一定是可以優化的,我的優化思路就是朝著時間復雜度的方向優化,O(n^3)就會考慮怎樣優化到O(n^2)或O(n^2lgn),O(n^2)就考慮如何優化到O(nlgn),當然巧用排序和二分查找也是順帶的想法。希望對你有些幫助
java代碼參考:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
int[] b = new int[n];
int[] c = new int[n];
for (int i = 0; i < a.length; i++) {
a[i] = sc.nextInt();
}
for (int i = 0; i < a.length; i++) {
b[i] = sc.nextInt();
}
for (int i = 0; i < a.length; i++) {
c[i] = sc.nextInt();
}
int res = solve2(a, b, c, n);
System.out.println(res);
}
/**
* 將三個數組排序(O(nlgn))
* 統計a數組中每個數在b中比該數大的個數
* 在枚舉b中每個數c中更大的個數,乘積和即為所求
* O(n^2)
* @param a
* @param b
* @param c
* @param n
* @return
*/
private static int solve2(int[] a, int[] b, int[] c, int n) {
int[] b_amax = new int[n];
int ans = 0;
Arrays.sort(a);Arrays.sort(b);Arrays.sort(c);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(b[j] > a[i]) {
b_amax[i] = n - j;
break;
}
}
}
//枚舉b,計算結果
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(c[j] > b[i]) {
ans += (n - j)*b_amax[i];
break;
}
}
}
return ans;
}
//暴力求解 O(n^3)
private static int solve(int[] a, int[] b, int[] c, int n) {
int ans = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
for(int k = 0; k < n; k++) {
if(a[i] < b[j]&&b[j] < c[k])
ans++;
}
}
}
return ans;
}
}