leecode,rt_phm更新更新
This commit is contained in:
parent
00f5d9ebd1
commit
67bcb4b0bc
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.markilue.leecode.hot100.interviewHot.singlestack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100.interviewHot.singlestack
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-25 11:29
|
||||||
|
*@Description: TODO 力扣239 滑动窗口最大值
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class LC_239_MaxSlidingWindow {
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ import java.util.LinkedList;
|
||||||
*@Description: TODO 力扣503 下一个更大元素II
|
*@Description: TODO 力扣503 下一个更大元素II
|
||||||
*@Version: 1.0
|
*@Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class T503_NextGreaterElements {
|
public class LC_503_NextGreaterElements {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.markilue.leecode.hot100.interviewHot.speical;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-25 10:39
|
||||||
|
*@Description: TODO 力扣238 除自身以外数组的乘积
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T71_238_ProductExceptSelf {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
int[] nums = {1, 2, 3, 4};
|
||||||
|
System.out.println(Arrays.toString(productExceptSelf(nums)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//思路:考虑分别使用一个left和right记录这个数左边数的乘积和右边数的乘积,最后计算总和
|
||||||
|
//其实本题的矛盾点就在于:如果不想要当前,就会损失前面的或者后面的,就会瞻前顾后,遍历两次即可
|
||||||
|
public int[] productExceptSelf(int[] nums) {
|
||||||
|
int[] left = new int[nums.length];
|
||||||
|
int[] right = new int[nums.length];
|
||||||
|
left[0] = 1;
|
||||||
|
right[nums.length - 1] = 1;
|
||||||
|
for (int i = 1; i < nums.length; i++) {
|
||||||
|
left[i] = left[i - 1] * nums[i - 1];
|
||||||
|
}
|
||||||
|
for (int i = nums.length - 2; i >= 0; i--) {
|
||||||
|
right[i] = right[i + 1] * nums[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < left.length; i++) {
|
||||||
|
left[i] *= right[i];
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ public class T67_221_MaximalSquare {
|
||||||
{'1', '1', '1', '1', '1'},
|
{'1', '1', '1', '1', '1'},
|
||||||
{'1', '0', '0', '1', '0'}
|
{'1', '0', '0', '1', '0'}
|
||||||
};
|
};
|
||||||
System.out.println(maximalSquare(matrix));
|
System.out.println(maximalSquare1(matrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -76,4 +76,28 @@ public class T67_221_MaximalSquare {
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int maximalSquare1(char[][] matrix) {
|
||||||
|
int m = matrix.length;
|
||||||
|
int n = matrix[0].length;
|
||||||
|
int[][] dp = new int[m][n];
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
if (matrix[i][j] == '1') {
|
||||||
|
if (i < 1 || j < 1) {
|
||||||
|
dp[i][j] = 1;//因为第一层最多只有1
|
||||||
|
} else {
|
||||||
|
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;//值得注意的是添加了dp[i-1][j-1]
|
||||||
|
//因为正方形需要全是1,而对角为0的情况可能可能会计算出同样的结果
|
||||||
|
}
|
||||||
|
result = Math.max(result, dp[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result * result;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.markilue.leecode.hot100.second;
|
||||||
|
|
||||||
|
import com.markilue.leecode.tree.TreeNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-25 10:31
|
||||||
|
*@Description: TODO 力扣236 二叉树的最近公共祖先
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T70_236_LowestCommonAncestor {
|
||||||
|
|
||||||
|
//思路:先遍历到谁,谁就一定是最大的,其他的可能在子树上;或者在另一个树上;两者返回值都可以确定
|
||||||
|
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
|
||||||
|
if (root == null) {
|
||||||
|
return root;
|
||||||
|
} else if (root == p) {
|
||||||
|
return p;
|
||||||
|
} else if (root == q) {
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
//全都没碰到:在当前节点的子树上
|
||||||
|
TreeNode left = lowestCommonAncestor(root.left, p, q);
|
||||||
|
TreeNode right = lowestCommonAncestor(root.right, p, q);
|
||||||
|
if (left != null && right != null) {
|
||||||
|
return root;
|
||||||
|
}else if(left==null){
|
||||||
|
return right;
|
||||||
|
}else {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//优秀写法
|
||||||
|
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
|
||||||
|
if (root == null || root == p || root == q) return root;
|
||||||
|
TreeNode left = lowestCommonAncestor(root.left, p, q);
|
||||||
|
TreeNode right = lowestCommonAncestor(root.right, p, q);
|
||||||
|
if (left != null && right != null) {return root;}
|
||||||
|
return left != null ? left : right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.markilue.leecode.hot100.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-25 10:39
|
||||||
|
*@Description: TODO 力扣238 除自身以外数组的乘积
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T71_238_ProductExceptSelf {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
int[] nums = {1, 2, 3, 4};
|
||||||
|
System.out.println(Arrays.toString(productExceptSelf(nums)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//思路:考虑分别使用一个left和right记录这个数左边数的乘积和右边数的乘积,最后计算总和
|
||||||
|
//其实本题的矛盾点就在于:如果不想要当前,就会损失前面的或者后面的,就会瞻前顾后,遍历两次即可
|
||||||
|
public int[] productExceptSelf(int[] nums) {
|
||||||
|
int[] left = new int[nums.length];
|
||||||
|
int[] right = new int[nums.length];
|
||||||
|
left[0] = 1;
|
||||||
|
right[nums.length - 1] = 1;
|
||||||
|
for (int i = 1; i < nums.length; i++) {
|
||||||
|
left[i] = left[i - 1] * nums[i - 1];
|
||||||
|
}
|
||||||
|
for (int i = nums.length - 2; i >= 0; i--) {
|
||||||
|
right[i] = right[i + 1] * nums[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < left.length; i++) {
|
||||||
|
left[i] *= right[i];
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.markilue.leecode.hot100.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-25 10:56
|
||||||
|
*@Description: TODO 力扣239 滑动窗口最大值
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T72_239_MaxSlidingWindow {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test(){
|
||||||
|
int[] nums = {1, 3, -1, -3, 5, 3, 6, 7};
|
||||||
|
int k = 3;
|
||||||
|
System.out.println(Arrays.toString(maxSlidingWindow(nums,k)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test1(){
|
||||||
|
int[] nums = {1,-1};
|
||||||
|
int k = 1;
|
||||||
|
System.out.println(Arrays.toString(maxSlidingWindow(nums,k)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用一个单调栈进行记录:定期排除过期元素
|
||||||
|
public int[] maxSlidingWindow(int[] nums, int k) {
|
||||||
|
ArrayDeque<int[]> stack = new ArrayDeque<>();//[num,index]
|
||||||
|
int[] result = new int[nums.length - k + 1];
|
||||||
|
|
||||||
|
//先入栈前k个,确定result的第一个位置,以后每移动一位,result也赋值一位
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
result[0] = Math.max(result[0], nums[i]);
|
||||||
|
while (!stack.isEmpty() && stack.peek()[0] < nums[i]) {
|
||||||
|
//在他前面,还比他小,那么一定不用记录了
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
stack.addFirst(new int[]{nums[i], i});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = k; i < nums.length; i++) {
|
||||||
|
//先清理掉尾部过期元素
|
||||||
|
while (!stack.isEmpty() && (i - stack.peekLast()[1]) >= k) {
|
||||||
|
//超过窗口了
|
||||||
|
stack.pollLast();
|
||||||
|
}
|
||||||
|
//将当前元素记录在stack中
|
||||||
|
while (!stack.isEmpty() && stack.peek()[0] < nums[i]) {
|
||||||
|
//在他前面,还比他小,那么一定不用记录了
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
stack.addFirst(new int[]{nums[i], i});
|
||||||
|
result[i - k + 1] = stack.peekLast()[0];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.markilue.leecode.hot100.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-25 11:31
|
||||||
|
*@Description: TODO 力扣240 搜索二维矩阵II
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T73_240_SearchMatrix {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
int[][] nums = {{1, 1}};
|
||||||
|
System.out.println(searchMatrix(nums, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//从左上角开始遍历:那么满足:target比当前值大,则向下;反之则向左
|
||||||
|
public boolean searchMatrix(int[][] matrix, int target) {
|
||||||
|
//左上角第一个数
|
||||||
|
int nowI = 0;
|
||||||
|
int nowJ = matrix[0].length - 1;
|
||||||
|
|
||||||
|
while (nowI < matrix.length && nowJ >= 0) {
|
||||||
|
if (matrix[nowI][nowJ] == target) {
|
||||||
|
return true;
|
||||||
|
} else if (matrix[nowI][nowJ] < target) {
|
||||||
|
nowI++;
|
||||||
|
} else {
|
||||||
|
nowJ--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.markilue.leecode.hot100.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100.second
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-25 11:42
|
||||||
|
*@Description: TODO 力扣279 完全平方数
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T74_279_NumSquares {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
System.out.println(numSquares(12));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int numSquares(int n) {
|
||||||
|
if (n < 1) return 0;
|
||||||
|
int[] dp = new int[n + 1];
|
||||||
|
dp[1] = 1;
|
||||||
|
for (int i = 2; i < dp.length; i++) {
|
||||||
|
dp[i] = i;//最多i个
|
||||||
|
for (int j = 1; j <= Math.sqrt(i); j++) {
|
||||||
|
dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
目前,有四种类型的变换可用:
|
目前,有四种类型的变换可用:
|
||||||
离散傅里叶变换(DFT)、离散余弦变换(DCT)、离散正弦变换(DST)和离散哈特利变换(DHT)-->
|
离散傅里叶变换(DFT)、离散余弦变换(DCT)、离散正弦变换(DST)和离散哈特利变换(DHT)-->
|
||||||
<!--使用教程:http://wendykierp.github.io/JTransforms/apidocs/-->
|
<!--使用教程:http://wendykierp.github.io/JTransforms/apidocs/-->
|
||||||
|
<!--经过测试,结果暂时不对-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.wendykierp</groupId>
|
<groupId>com.github.wendykierp</groupId>
|
||||||
<artifactId>JTransforms</artifactId>
|
<artifactId>JTransforms</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.cqu.algorithm.fft;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: phm_parent
|
||||||
|
*@BelongsPackage: com.cqu.algorithm.fft
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-24 15:24
|
||||||
|
*@Description: TODO 构建Complex数组
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class BulidComplex {
|
||||||
|
|
||||||
|
public static Complex[] build(List<Double> raw) {
|
||||||
|
Complex[] complexes = new Complex[raw.size()];
|
||||||
|
for (int i = 0; i < complexes.length; i++) {
|
||||||
|
complexes[i] = new Complex(raw.get(i));
|
||||||
|
}
|
||||||
|
return complexes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.cqu.algorithm.fft;
|
||||||
|
|
||||||
|
public class Complex {
|
||||||
|
//复数类,实现复数的加减乘除以及重写toString方法
|
||||||
|
private double real;
|
||||||
|
private double image;
|
||||||
|
|
||||||
|
public Complex() {
|
||||||
|
this(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Complex (double real) {
|
||||||
|
this(real,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Complex(double real,double image) {
|
||||||
|
this.real = real;
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Complex plus(Complex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
double newReal =real + real2;
|
||||||
|
double newImage =image + image2;
|
||||||
|
return new Complex(newReal,newImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Complex minus(Complex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
double newReal =real - real2;
|
||||||
|
double newImage =image - image2;
|
||||||
|
return new Complex(newReal,newImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Complex multiply(Complex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
double newReal = real * real2 - image * image2;
|
||||||
|
double newImage = image * real2 + real * image2;
|
||||||
|
return new Complex(newReal,newImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Complex divide(Complex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
double newReal = (real*real2 + image*image2)/(real2*real2 + image2*image2);
|
||||||
|
double newImage = (image*real2 - real*image2)/(real2*real2 + image2*image2);
|
||||||
|
return new Complex(newReal,newImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
//计算真实大小的时部和虚部
|
||||||
|
public Complex divide(int dim) {
|
||||||
|
real = real * 2 / dim;
|
||||||
|
image = image * 2 / dim;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//计算振幅
|
||||||
|
public double getAmplitude() {
|
||||||
|
return Math.sqrt(real * real + image * image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getReal() {
|
||||||
|
return real;
|
||||||
|
}
|
||||||
|
public void setReal(double real) {
|
||||||
|
this.real = real;
|
||||||
|
}
|
||||||
|
public double getImage() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
public void setImage(double image) {
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "real=" + real + ", image=" + image;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.cqu.algorithm.fft;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: phm_parent
|
||||||
|
*@BelongsPackage: com.cqu.algorithm.fft
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-24 15:24
|
||||||
|
*@Description: TODO DFT算法的实现类
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class DFT {
|
||||||
|
//DFT计算
|
||||||
|
public static Complex[] dft(Complex[] x,int N) {
|
||||||
|
|
||||||
|
if(N == 1 || x.length == 1) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
Complex result[] = new Complex[N];
|
||||||
|
for(int k = 0; k < N; k++) {
|
||||||
|
result[k] = new Complex();
|
||||||
|
for(int n = 0; n<N; n++) {
|
||||||
|
double W = -2*n*k*Math.PI/N;
|
||||||
|
Complex c = new Complex(Math.cos(W),Math.sin(W));
|
||||||
|
result[k] = result[k].plus(x[n].multiply(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,148 @@
|
||||||
package com.cqu.algorithm.fft;
|
package com.cqu.algorithm.fft;
|
||||||
|
|
||||||
import org.jtransforms.fft.BenchmarkDoubleFFT;
|
|
||||||
import org.jtransforms.fft.BenchmarkFloatFFT;
|
|
||||||
import org.jtransforms.fft.DoubleFFT_1D;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*@BelongsProject: phm_parent
|
*@BelongsProject: phm_parent
|
||||||
*@BelongsPackage: com.cqu.algorithm.fft
|
*@BelongsPackage: com.cqu.algorithm.fft
|
||||||
*@Author: markilue
|
*@Author: markilue
|
||||||
*@CreateTime: 2023-05-23 20:19
|
*@CreateTime: 2023-05-24 15:24
|
||||||
*@Description: TODO FFT类
|
*@Description: TODO FFT算法的实现类
|
||||||
*@Version: 1.0
|
*@Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class FFT {
|
public class FFT {
|
||||||
|
public static Complex[] fft(Complex[] x,int N) {
|
||||||
|
//定义式计算FFT(方法一)
|
||||||
|
if(N == 1 ) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
// 如果信号数为奇数,使用dft计算
|
||||||
|
if(N % 2 != 0) {
|
||||||
|
return DFT.dft(x, N);
|
||||||
|
}
|
||||||
|
// 提取下标为偶数的原始信号值进行递归fft计算
|
||||||
|
Complex[] even = new Complex[N / 2];
|
||||||
|
for (int k = 0; k < even.length; k++) {
|
||||||
|
even[k] = x[2 * k];
|
||||||
|
}
|
||||||
|
Complex[] evenValue = FFT.fft(even, even.length);
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
// 提取下标为奇数的原始信号值进行fft计算
|
||||||
|
// 节约内存
|
||||||
new DoubleFFT_1D(10).complexForward(new double[10]);
|
Complex[] odd = even;
|
||||||
|
for (int k = 0; k < odd.length; k++) {
|
||||||
|
odd[k] = x[2 * k + 1];
|
||||||
|
}
|
||||||
|
Complex[] oddValue = FFT.fft(odd,odd.length);
|
||||||
|
// 偶数+奇数
|
||||||
|
Complex[] result = new Complex[N];
|
||||||
|
for (int k = 0; k < N / 2; k++) {
|
||||||
|
double W = -2*k*Math.PI/N;
|
||||||
|
Complex m = new Complex(Math.cos(W), Math.sin(W));
|
||||||
|
result[k] = evenValue[k].plus(m.multiply(oddValue[k]));
|
||||||
|
result[k + N / 2] = evenValue[k].minus(m.multiply(oddValue[k]));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reverse(Complex[] A,int N) {
|
||||||
|
//倒叙前N个数据
|
||||||
|
int LH = N/2;
|
||||||
|
int J = LH;
|
||||||
|
int N1 = N-2;
|
||||||
|
for(int I = 1;I <= N1; I++) {
|
||||||
|
if(!(I >=J)) {
|
||||||
|
Complex T = A[I];
|
||||||
|
A[I] = A[J];
|
||||||
|
A[J] = T;
|
||||||
|
}
|
||||||
|
int K = LH;
|
||||||
|
while(!(J < K)) {
|
||||||
|
J = J - K;
|
||||||
|
K = K/2;
|
||||||
|
}
|
||||||
|
J += K;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//对复数数组倒叙
|
||||||
|
public static void reverse(Complex[] A) {
|
||||||
|
int N = A.length;
|
||||||
|
int LH = N/2;
|
||||||
|
int J = LH;
|
||||||
|
int N1 = N-2;
|
||||||
|
for(int I = 1;I <= N1; I++) {
|
||||||
|
if(!(I >=J)) {
|
||||||
|
Complex T = A[I];
|
||||||
|
A[I] = A[J];
|
||||||
|
A[J] = T;
|
||||||
|
}
|
||||||
|
int K = LH;
|
||||||
|
while(!(J < K)) {
|
||||||
|
J = J - K;
|
||||||
|
K = K/2;
|
||||||
|
}
|
||||||
|
J += K;
|
||||||
|
|
||||||
|
}
|
||||||
|
// return null;
|
||||||
|
}
|
||||||
|
public static Complex[] myFFT(Complex[] A,int N) {
|
||||||
|
//FFT计算(方法二)推荐这一种,错误小
|
||||||
|
int M = returnM(N);
|
||||||
|
Complex[] x = new Complex[N];
|
||||||
|
System.arraycopy(A, 0, x, 0, N);
|
||||||
|
reverse(x);
|
||||||
|
for(int L = 1;L <= M;L++) {
|
||||||
|
int B = (int)Math.pow(2, L-1);
|
||||||
|
for(int J = 0;J <= B-1;J++) {
|
||||||
|
int P = (int)Math.pow(2, M-L)*J;
|
||||||
|
for(int k = J;k <= N-1;k += Math.pow(2, L)) {
|
||||||
|
double W = -2*Math.PI*P/N;
|
||||||
|
Complex c = x[k+B].multiply(new Complex(Math.cos(W),Math.sin(W)));
|
||||||
|
Complex T = x[k].plus(c);
|
||||||
|
x[k+B] = x[k].minus(c);
|
||||||
|
x[k] = T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Complex[] myFFT(Complex[] A,int offset,int N) {
|
||||||
|
//FFT计算,计算从offset开始的N条数据
|
||||||
|
int M = returnM(N);
|
||||||
|
Complex[] x = new Complex[N];
|
||||||
|
System.arraycopy(A, offset, x, 0, N);
|
||||||
|
reverse(x);
|
||||||
|
for(int L = 1;L <= M;L++) {
|
||||||
|
int B = (int)Math.pow(2, L-1);
|
||||||
|
for(int J = 0;J <= B-1;J++) {
|
||||||
|
int P = (int)Math.pow(2, M-L)*J;
|
||||||
|
for(int k = J;k <= N-1;k += Math.pow(2, L)) {
|
||||||
|
double W = -2*Math.PI*P/N;
|
||||||
|
Complex c = x[k+B].multiply(new Complex(Math.cos(W),Math.sin(W)));
|
||||||
|
Complex T = x[k].plus(c);
|
||||||
|
x[k+B] = x[k].minus(c);
|
||||||
|
x[k] = T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回一个数是2的几次幂
|
||||||
|
public static int returnM(int N) {
|
||||||
|
// int N = x.length;
|
||||||
|
if((N&(N-1))!=0) {
|
||||||
|
throw new RuntimeException("非2的整数幂");
|
||||||
|
}
|
||||||
|
int M=0;
|
||||||
|
while((N = N / 2) != 0) {
|
||||||
|
M++;
|
||||||
|
}
|
||||||
|
return M;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.cqu.algorithm.fft;
|
||||||
|
|
||||||
|
import javax.print.DocFlavor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: phm_parent
|
||||||
|
*@BelongsPackage: com.cqu.algorithm.fft
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-24 15:24
|
||||||
|
*@Description:
|
||||||
|
* TODO 每一个点的复数类;real表示实数;image表示虚数
|
||||||
|
* 使用函数式编程接口:加减乘除都改变自身
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class MutableComplex {
|
||||||
|
//复数类,实现复数的加减乘除以及重写toString方法
|
||||||
|
private double real;
|
||||||
|
private double image;
|
||||||
|
|
||||||
|
public MutableComplex() {
|
||||||
|
this(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableComplex(double real) {
|
||||||
|
this(real, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableComplex(double real, double image) {
|
||||||
|
this.real = real;
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableComplex plus(MutableComplex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
real = real + real2;
|
||||||
|
image = image + image2;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableComplex minus(MutableComplex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
real = real - real2;
|
||||||
|
image = image - image2;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableComplex multiply(MutableComplex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
real = real * real2 - image * image2;
|
||||||
|
image = image * real2 + real * image2;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableComplex divide(MutableComplex complex) {
|
||||||
|
double real2 = complex.getReal();
|
||||||
|
double image2 = complex.getImage();
|
||||||
|
real = (real * real2 + image * image2) / (real2 * real2 + image2 * image2);
|
||||||
|
image = (image * real2 - real * image2) / (real2 * real2 + image2 * image2);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//计算真实大小的时部和虚部
|
||||||
|
public MutableComplex divide(int dim) {
|
||||||
|
real = real * 2 / dim;
|
||||||
|
image = image * 2 / dim;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getReal() {
|
||||||
|
return real;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReal(double real) {
|
||||||
|
this.real = real;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getImage() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImage(double image) {
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
//计算振幅
|
||||||
|
public double getAmplitude() {
|
||||||
|
return Math.sqrt(real * real + image * image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "real=" + real + ", image=" + image;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.cqu.algorithm.fft;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试
|
||||||
|
*/
|
||||||
|
public class TestComplex {
|
||||||
|
//测试复数运算
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Complex complex1 = new Complex(5);
|
||||||
|
Complex complex2 = new Complex(4);
|
||||||
|
System.out.println(complex1.multiply(complex2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.cqu.algorithm.fft;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试FFT
|
||||||
|
*/
|
||||||
|
public class TestFFT {
|
||||||
|
//测试DFT、FFT运算
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
// test1();
|
||||||
|
test3();
|
||||||
|
}
|
||||||
|
public static void test1() {
|
||||||
|
Complex[] x = new Complex[5];
|
||||||
|
x[0] = new Complex(4);
|
||||||
|
x[1] = new Complex(3);
|
||||||
|
x[2] = new Complex(2);
|
||||||
|
x[3] = new Complex(1);
|
||||||
|
x[4] = new Complex(0);
|
||||||
|
for(Complex a:x) {
|
||||||
|
System.out.println(a);
|
||||||
|
}
|
||||||
|
Complex[] x1 = DFT.dft(x, 5);
|
||||||
|
for(Complex a:x1) {
|
||||||
|
System.out.println(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void test2() {
|
||||||
|
Complex[] x = new Complex[8];
|
||||||
|
for(int i = 0;i < x.length;i++) {
|
||||||
|
x[i] = new Complex(i);
|
||||||
|
}
|
||||||
|
for(Complex a:x) {
|
||||||
|
System.out.println(a);
|
||||||
|
}
|
||||||
|
Complex[] x1 = DFT.dft(x, 8);
|
||||||
|
Complex[] x2 = FFT.fft(x, 8);
|
||||||
|
Complex[] x3 = FFT.myFFT(x, 8);
|
||||||
|
|
||||||
|
for (int i = 0; i < x3.length; i++) {
|
||||||
|
System.out.println(x1[i] + "/" + x2[i] + "/" + x3[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test3() {
|
||||||
|
|
||||||
|
Complex[] x = BulidComplex.build(Arrays.asList(-0.029078494757,
|
||||||
|
-0.33095228672,
|
||||||
|
-0.12124221772,
|
||||||
|
0.553512275219,
|
||||||
|
-0.158036053181,
|
||||||
|
0.268739402294,
|
||||||
|
-0.638222515583,
|
||||||
|
0.233140587807,
|
||||||
|
-0.173265621066,
|
||||||
|
0.467218101025,
|
||||||
|
-0.372010827065,
|
||||||
|
-0.136630430818,
|
||||||
|
0.343256533146,
|
||||||
|
0.008932195604));
|
||||||
|
for(Complex a:x) {
|
||||||
|
System.out.println(a);
|
||||||
|
}
|
||||||
|
Complex[] x1 = DFT.dft(x, 14);
|
||||||
|
Complex[] x2 = FFT.fft(x, 14);
|
||||||
|
// Complex[] x3 = FFT.myFFT(x, 14);
|
||||||
|
|
||||||
|
for (int i = 0; i < x2.length; i++) {
|
||||||
|
System.out.println(x1[i] + "/" + x2[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -29,6 +29,7 @@ public abstract class BaseStreamApp {
|
||||||
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, 3000L));
|
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, 3000L));
|
||||||
env.setStateBackend(new FsStateBackend(PHMConfig.RT_CHECKPOINT_LOCATION));
|
env.setStateBackend(new FsStateBackend(PHMConfig.RT_CHECKPOINT_LOCATION));
|
||||||
System.setProperty("HADOOP_USER_NAME", PHMConfig.HADOOP_USER_NAME);
|
System.setProperty("HADOOP_USER_NAME", PHMConfig.HADOOP_USER_NAME);
|
||||||
|
System.setProperty("java.vm.name","Java HotSpot(TM) ");//使用的JDK版本
|
||||||
//模板
|
//模板
|
||||||
execute(env);
|
execute(env);
|
||||||
env.execute();
|
env.execute();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.cqu.warehouse.realtime.app.base.BaseStreamApp;
|
import com.cqu.warehouse.realtime.app.base.BaseStreamApp;
|
||||||
import com.cqu.warehouse.realtime.app.func.DataSamplingFunction;
|
import com.cqu.warehouse.realtime.app.func.DataSamplingFunction;
|
||||||
|
import com.cqu.warehouse.realtime.app.func.FFTSamplingFunction;
|
||||||
import com.cqu.warehouse.realtime.utils.MyKafkaUtils;
|
import com.cqu.warehouse.realtime.utils.MyKafkaUtils;
|
||||||
|
import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
|
||||||
import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
|
import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
|
||||||
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
|
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
|
||||||
import org.apache.flink.api.common.functions.RichMapFunction;
|
import org.apache.flink.api.common.functions.RichMapFunction;
|
||||||
|
|
@ -200,6 +202,10 @@ public class WindCMSApp extends BaseStreamApp {
|
||||||
@Override
|
@Override
|
||||||
public void process(Tuple2<String, String> stringStringTuple2, ProcessWindowFunction<JSONObject, JSONObject, Tuple2<String, String>, TimeWindow>.Context context, Iterable<JSONObject> iterable, Collector<JSONObject> collector) throws Exception {
|
public void process(Tuple2<String, String> stringStringTuple2, ProcessWindowFunction<JSONObject, JSONObject, Tuple2<String, String>, TimeWindow>.Context context, Iterable<JSONObject> iterable, Collector<JSONObject> collector) throws Exception {
|
||||||
JSONObject obj = null;
|
JSONObject obj = null;
|
||||||
|
//参考:https://zhuanlan.zhihu.com/p/534376156
|
||||||
|
//经过测试:1000个点一发:iterable500M
|
||||||
|
//10000个点一发:iterable370M
|
||||||
|
System.out.println("iterable_data_size:" + ObjectSizeCalculator.getObjectSize(iterable));
|
||||||
for (JSONObject jsonObject : iterable) {
|
for (JSONObject jsonObject : iterable) {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
obj = jsonObject;
|
obj = jsonObject;
|
||||||
|
|
@ -212,15 +218,40 @@ public class WindCMSApp extends BaseStreamApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
//TODO 合并的结果大概有10000个数据:判断是否合理
|
|
||||||
mergeDS.print(">>>");
|
|
||||||
|
|
||||||
//TODO 5.写回kafka
|
|
||||||
mergeDS
|
//TODO 6.计算频谱 --不知道要计算多久,使用异步Stream进行计算
|
||||||
.map(jsonObject -> jsonObject.toJSONString())
|
SingleOutputStreamOperator<JSONObject> fftDS = AsyncDataStream.unorderedWait(
|
||||||
.addSink(
|
mergeDS,
|
||||||
MyKafkaUtils.getKafkaSink("dwm_wind_cms_10_downsampling")
|
new FFTSamplingFunction<JSONObject>() {
|
||||||
|
@Override
|
||||||
|
protected void setTransformData(JSONObject jsonObject, List<Double> fft) {
|
||||||
|
jsonObject.put("x", fft);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Double> getTransformData(JSONObject jsonObject) {
|
||||||
|
return jsonObject.getJSONArray("x").toJavaList(Double.class);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
60, TimeUnit.SECONDS
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//TODO 合并的结果大概有10000个数据:判断是否合理
|
||||||
|
mergeDS.print(">>>");
|
||||||
|
// fftDS.print(">>>");
|
||||||
|
|
||||||
|
//TODO 5.写回kafka
|
||||||
|
// mergeDS
|
||||||
|
// .map(jsonObject -> jsonObject.toJSONString())
|
||||||
|
// .addSink(
|
||||||
|
// MyKafkaUtils.getKafkaSink("dwm_wind_cms_10_downsampling")
|
||||||
|
// );
|
||||||
|
// fftDS
|
||||||
|
// .map(jsonObject -> jsonObject.toJSONString())
|
||||||
|
// .addSink(
|
||||||
|
// MyKafkaUtils.getKafkaSink("dwm_wind_cms_10_frequency")
|
||||||
|
// );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.cqu.warehouse.realtime.app.func;
|
||||||
|
|
||||||
|
import com.cqu.warehouse.realtime.utils.TransformUtils;
|
||||||
|
import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
|
||||||
|
import org.apache.flink.streaming.api.functions.async.AsyncFunction;
|
||||||
|
import org.apache.flink.streaming.api.functions.async.ResultFuture;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: phm_parent
|
||||||
|
*@BelongsPackage: com.cqu.warehouse.realtime.app.func
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-05-24 17:46
|
||||||
|
*@Description: TODO 计算数据的FFT
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public abstract class FFTSamplingFunction<T> implements AsyncFunction<T, T> {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void asyncInvoke(T t, ResultFuture<T> resultFuture) throws Exception {
|
||||||
|
List<Double> transformData = getTransformData(t);
|
||||||
|
List<Double> fft = TransformUtils.fft(transformData);
|
||||||
|
setTransformData(t,fft);
|
||||||
|
System.out.println("fftDataSize:"+ObjectSizeCalculator.getObjectSize(t));
|
||||||
|
resultFuture.complete(Collections.singleton(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void setTransformData(T t, List<Double> fft);
|
||||||
|
|
||||||
|
protected abstract List<Double> getTransformData(T t);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,12 @@
|
||||||
package com.cqu.warehouse.realtime.utils;
|
package com.cqu.warehouse.realtime.utils;
|
||||||
|
|
||||||
|
import com.cqu.algorithm.fft.Complex;
|
||||||
|
import com.cqu.algorithm.fft.FFT;
|
||||||
import org.jtransforms.dct.DoubleDCT_1D;
|
import org.jtransforms.dct.DoubleDCT_1D;
|
||||||
import org.jtransforms.fft.DoubleFFT_1D;
|
import org.jtransforms.fft.DoubleFFT_1D;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,21 +20,59 @@ import java.util.List;
|
||||||
* 2)DCT
|
* 2)DCT
|
||||||
* 3)DST
|
* 3)DST
|
||||||
* 4)DHT
|
* 4)DHT
|
||||||
|
* 参考: <!--使用教程:http://wendykierp.github.io/JTransforms/apidocs/-->
|
||||||
*@Version: 1.0
|
*@Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class TransformUtils {
|
public class TransformUtils {
|
||||||
|
|
||||||
public static void fft(double[] data) {
|
private static Complex[] buildComplex(double[] raw) {
|
||||||
new DoubleFFT_1D(data.length).complexForward(data);
|
Complex[] complexes = new Complex[raw.length];
|
||||||
|
for (int i = 0; i < complexes.length; i++) {
|
||||||
|
complexes[i] = new Complex(raw[i]);
|
||||||
|
}
|
||||||
|
return complexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double[] fft(List<Double> data) {
|
private static Complex[] buildComplex(List<Double> raw) {
|
||||||
double[] raw = new double[data.size()];
|
Complex[] complexes = new Complex[raw.size()];
|
||||||
for (int i = 0; i < raw.length; i++) {
|
for (int i = 0; i < complexes.length; i++) {
|
||||||
raw[i] = data.get(i);
|
complexes[i] = new Complex(raw.get(i));
|
||||||
}
|
}
|
||||||
// fft(data.toArray(new Double[0]));
|
return complexes;
|
||||||
fft(raw);
|
}
|
||||||
return raw;
|
|
||||||
|
public static List<Double> fft(double[] data) {
|
||||||
|
Complex[] raw = buildComplex(data);
|
||||||
|
Complex[] fft = FFT.fft(raw, raw.length);
|
||||||
|
return calculateAmplitude(fft);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Double> fft(List<Double> data) {
|
||||||
|
Complex[] raw = buildComplex(data);
|
||||||
|
Complex[] fft = FFT.fft(raw, raw.length);
|
||||||
|
return calculateAmplitude(fft);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Double> calculateAmplitude(Complex[] fft) {
|
||||||
|
List<Double> amplitudeList = new ArrayList<>();
|
||||||
|
for (Complex complex : fft) {
|
||||||
|
amplitudeList.add(complex.divide(fft.length).getAmplitude());
|
||||||
|
}
|
||||||
|
return amplitudeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
double[] array = {-0.029078494757, -0.33095228672, -0.12124221772, 0.553512275219, -0.158036053181,
|
||||||
|
0.268739402294,
|
||||||
|
-0.638222515583,
|
||||||
|
0.233140587807,
|
||||||
|
-0.173265621066,
|
||||||
|
0.467218101025,
|
||||||
|
-0.372010827065,
|
||||||
|
-0.136630430818,
|
||||||
|
0.343256533146,
|
||||||
|
0.008932195604};
|
||||||
|
List<Double> fft = fft(array);
|
||||||
|
System.out.println(fft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue