【線性 dp】B007_NK_最長等差數列問題(暴力 dp / 預處理差)

一、Problem

給定一個未排序數組,找出其中最長的等差數列(無需保證數字順序)。

輸入描述:
第一行N表示數組中元素個數(N < 10,000,000)

第二行是數組的元素,用空格分割

輸出描述:
等差序列長度

示例1
輸入
5
1 4 2 5 3
輸出
5

二、Solution

這題居然能用 n2n^2 的複雜度算法過掉 10610^6 的數據,我也是服了…

方法一:dp

  • 定義狀態
    • f[i][d]f[i][d] 表示在數列的第 ii 個位置時,公差爲 dd 的最差等差數列長度。
  • 思考初始化:
    • f[0]=0f[0] = 0
  • 思考狀態轉移方程
    • f[i][d]=f[j][d]+1f[i][d] = f[j][d] + 1
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    static class Solution {
        void init() {
            Scanner sc = new Scanner(new BufferedInputStream(System.in));
            int n = sc.nextInt(), sum = 0, a[] = new int[n];
            if (n <= 2) {
                System.out.println(n);
                return;
            }
            for (int i = 0; i < n; i++) a[i] = sc.nextInt();
            Arrays.sort(a);
            int ans = 2;
            Map<Integer, Integer>[] f = new HashMap[n];
 
            for (int i = 0; i < n; i++) {
                f[i] = new HashMap<>();
                for (int j = 0; j < i; j++) {
                    int d = a[i] - a[j];
                    int len = f[j].getOrDefault(d, 1) + 1;
                    ans = Math.max(ans, len);
                    f[i].put(d, len);
                }
            }
            System.out.println(ans);
        } 
    }
    public static void main(String[] args) throws IOException {
        Solution s = new Solution();
        s.init();
    }
}

C++ 由於有運算符重載,所以代碼寫比較直觀

for(int i=0;i<n;i++)
for(int j=0;j<i;j++){ //每次計算i的時候,只需要比較i前面所有的和當前i的差。
    int key = A[j] -A[i];
    if(dp[j][d] != 0){
 		dp[i][d] = dp[j][d] + 1;
	else
  		dp[i][d] = 2;
    ans = max(ans , dp[i][d]);
}

複雜度分析

  • 時間複雜度:O(n2)O(n^2)
  • 空間複雜度:O(n)O(n)

方法二:預處理兩數之差

預處理出個兩個數的差到數組中,因爲題目並沒有規定數字的順序,所以可用 map 記錄每個公比出現次數,最後返回每個公比的最大次數即可。

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
    static class Solution {
        void init() {
            Scanner sc = new Scanner(new BufferedInputStream(System.in));
            int n = sc.nextInt(), a[] = new int[n];
            if (n <= 2) {
                System.out.println(n);
                return;
            }
            for (int i = 0; i < n; i++) a[i] = sc.nextInt();
            Arrays.sort(a);
            int ans = 2, d[] = new int[n];
            d[0] = Integer.MAX_VALUE;
            Map<Integer, Integer> mp = new HashMap<>();
            
            for (int i = 1; i < n; i++) {
                d[i] = a[i] - a[i-1];
                if (d[i] == d[i-1])
                    mp.put(d[i], mp.getOrDefault(d[i], 2) + 1);
            }
            for (Map.Entry<Integer, Integer> e : mp.entrySet()) {
                ans = Math.max(ans, e.getValue());
            }
            System.out.println(ans);
        }  
    }
    public static void main(String[] args) throws IOException { 
        Solution s = new Solution();
        s.init();
    }
}

複雜度分析

  • 時間複雜度:O(nlogn)O(nlogn)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章