Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ch.fhnw.claudemartin.algd1.maxteilsumme;
- import java.util.Arrays;
- import java.util.Random;
- import java.util.concurrent.atomic.AtomicInteger;
- public class MaxT {
- static int naive(byte[] a) {
- int sum = 0;
- int x;
- loop1: for (int left = 0; left < a.length; left++) {
- while (a[left] <= 0)
- continue loop1;
- loop2: for (int right = a.length - 1; right >= left; right--) {
- while (a[right] <= 0)
- continue loop2;
- x = 0;
- for (int i = left; i <= right; i++) {
- x += a[i];
- }
- if (x > sum)
- sum = x;
- }
- }
- return sum;
- }
- public static void main(String[] args) {
- test(new byte[] { 42 });// 42
- test(new byte[] { -1, 0, 1 });// 1
- test(new byte[] { 1, 0, 1 });// 2
- test(new byte[] { 1, 1, 1 });// 3
- test(new byte[] { -1 });// 0
- test(new byte[] { 10, 21, -13, 7, 9, -4, -9, 21, -6, 13, 17, 12, 1, -7, -6, 9 });// 79
- test(new byte[] { 31, -41, 59, 26, -53, 58, 97, -93, -23, 84 });// 187
- for (int i = 0; i < 10; i++) {
- test(1000 + i);
- }
- for (int i = 0; i < 10; i++) {
- test((int) Math.pow(10, i));
- }
- }
- static int seed = 0;
- private static void test(int n) {
- Random random = new Random(seed++);
- final byte[] a = new byte[n];
- for (int i = 0; i < a.length; i++) {
- a[i] = (byte) ((random.nextDouble() - 0.5) * Byte.MAX_VALUE);
- }
- test(a);
- }
- private static void test(final byte[] a) {
- // int[] a = { 2, -1, 3 };
- // System.out.println(Arrays.toString(a));
- long start = System.currentTimeMillis();
- final int maxT = maxTeilsumme(a);
- long end = System.currentTimeMillis();
- System.out.println("length: " + a.length);
- System.out.println("result: " + maxT);
- System.out.println("time (ms): " + (end - start));
- if (a.length <= 5000) {
- final long s = System.currentTimeMillis();
- int naive = naive(a);
- if (maxT != naive) {
- System.err.println("Wrong result!!!");
- System.err.println("Naive result: " + naive);
- System.err.println("Array: " + Arrays.toString(a));
- }
- System.out.println("time of naive impl. (ms): " + (System.currentTimeMillis() - s));
- }
- System.out.println("----------------");
- }
- static int maxTeilsumme(final byte[] a) {
- if (a.length == 0)
- return 0;
- final int left = 0;
- final int right = a.length - 1;
- // erst bei sehr grossen Arrays lohnt sich Multithreading:
- if (a.length < 1000000)
- return maxTeilsumme(a, left, right);
- // else:
- // System.out.println(left+", "+right);
- final int m = left + ((right - left) >> 1);
- assert m > left && m < right;
- final AtomicInteger vLsum = new AtomicInteger();
- Thread t1 = new Thread() {
- public void run() {
- vLsum.set(maxTeilsumme(a, left, m));
- };
- };
- final AtomicInteger vRsum = new AtomicInteger();
- Thread t2 = new Thread() {
- public void run() {
- vRsum.set(maxTeilsumme(a, m + 1, right));
- };
- };
- final AtomicInteger asum = new AtomicInteger();
- Thread t3 = new Thread() {
- public void run() {
- asum.set(sum(a, left, right));
- };
- };
- t1.start();
- t2.start();
- t3.start();
- try {
- t1.join();
- t2.join();
- t3.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return max(vLsum.get(), vRsum.get(), asum.get());
- }
- static int maxTeilsumme(final byte[] a, final int left, final int right) {
- assert right >= left;
- // System.out.println(left+", "+right);
- switch (right - left) {
- case 0:
- return a[left] > 0 ? a[left] : 0;
- case 1:
- return max(0, a[left], a[right], a[left] + a[right]);
- case 2:
- final int lft = a[left];
- final int mid = a[right - 1];
- final int rgt = a[right];
- return max(0, lft, mid, rgt, a[left] + mid, mid + a[right], a[left] + mid + a[right]);
- case 3:
- final int a1 = a[left];// right-3
- final int a2 = a[left + 1];// right-2
- final int a3 = a[right - 1];// left+2
- final int a4 = a[right];// left+3
- final int a12 = a1 + a2;
- final int a34 = a3 + a4;
- return max(0, a1, a2, a3, a4, a12, a2 + a3, a34, a12 + a3, a2 + a34, a12 + a34);
- default:
- int m = left + ((right - left) >> 1);
- assert m > left && m < right;
- int vLsum = maxTeilsumme(a, left, m);
- int vRsum = maxTeilsumme(a, m + 1, right);
- int asum = sum(a, left, right);
- return max(vLsum, vRsum, asum);
- }
- }
- static int sum(byte[] a, int left, int right) {
- int sum = 0;
- int rmax = 0;
- int m = left + ((right - left) >> 1);
- for (int i = m + 1; i <= right; i++) {
- sum += a[i];
- if (sum > rmax)
- rmax = sum;
- }
- sum = 0;
- int lmax = 0;
- for (int i = m; i >= left; i--) {
- sum += a[i];
- if (sum > lmax)
- lmax = sum;
- }
- return lmax + rmax;
- }
- static int max(int... vals) {
- assert vals.length > 0;
- int rv = Integer.MIN_VALUE;
- for (int i : vals) {
- if (i > rv)
- rv = i;
- }
- assert rv != Integer.MIN_VALUE;
- return rv;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement