最长单调子序列算法不是最长增长算法

时间:2013-11-14 10:30:01

标签: java sequence subset monotone

我在输入处有一些数字:

1 1 7 3 2 0 0 4 5 5 6 2 1

我寻找最长的单调子序列,这个子序列的总和是多少。结果是:

6 20

我在互联网上找不到算法。你拥有/找到一个吗?这是最长的单调而不是最长的增长子序列。

单调的定义:http://en.wikipedia.org/wiki/Monotonic_function

我知道有人会问:你有什么尝试?所以我试着写它(请不要检查它我只发布它所以没有人问上面的问题我寻找不同的算法 - >最优的一个)导入

java.io.BufferedReader;
import java.io.InputStreamReader;

public class Rozwiazanie {
    public static void main(String[] args) {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

            //2^63 > 10^16 = 10^7 * 10^9 longi starcza
            //10^9 inty starcza
            //int 32 bity, long 64 bity
            long podsuma = 0;
            int dlugosc = 0;
            int maxDlugosc = 0;
            long maxPodsuma = 0;
            int poczatekRownych = 0;
            int poprzedniWyraz = 0, aktualnyWyraz;//uwaga jakby cos nie gralo w sprawdzarce zmien typ na long
            boolean czyRosnacy = false, rowny = false;
            String[] splittedLinia = br.readLine().split((char) 32 + "");//moglaby byc " " ale tak na wszelki wypadek nie ma chuja zeby sie popierdolilo teraz nawet na linuxie
            for (int i = 0; i < splittedLinia.length; i++) {
                if (i == 0) {
                    aktualnyWyraz = Integer.parseInt(splittedLinia[0]);
                    maxDlugosc = dlugosc = 1;
                    maxPodsuma = podsuma = aktualnyWyraz;
                    if (splittedLinia.length > 1) {
                        int nastepnyWyraz = Integer.parseInt(splittedLinia[1]);
                        czyRosnacy = nastepnyWyraz > aktualnyWyraz;
                        rowny = nastepnyWyraz == aktualnyWyraz;
                    }
                    System.out.println("akt: " + aktualnyWyraz + " pop: " + poprzedniWyraz + " dlugosc: " + dlugosc + " " + 1);
                } else {
                    aktualnyWyraz = Integer.parseInt(splittedLinia[i]);
                    System.out.println(rowny);
                    if (aktualnyWyraz == poprzedniWyraz && rowny) {
                        podsuma += aktualnyWyraz;
                        dlugosc++;
                        System.out.println("akt: " + aktualnyWyraz + " pop: " + poprzedniWyraz + " dlugosc: " + dlugosc + " " + 2);
                    } else if (rowny) {
                        rowny = false;
                        czyRosnacy = aktualnyWyraz > poprzedniWyraz;
                        System.out.println("akt: " + aktualnyWyraz + " pop: " + poprzedniWyraz + " dlugosc: " + dlugosc + " " + 3);
                    }

                    if (!rowny) {


                        if (aktualnyWyraz >= poprzedniWyraz && czyRosnacy) {
                            podsuma += aktualnyWyraz;
                            dlugosc++;
                            System.out.println("akt:" + aktualnyWyraz + " pop: " + poprzedniWyraz + " dlugosc: " + dlugosc + " " + 4);
                        } else if (aktualnyWyraz <= poprzedniWyraz && !czyRosnacy) {
                            podsuma += aktualnyWyraz;
                            dlugosc++;
                            System.out.println("akt: " + aktualnyWyraz + " pop: " + poprzedniWyraz + " dlugosc: " + dlugosc + " " + 5);
                        } else {
                            //  if (aktualnyWyraz == poprzedniWyraz) {
                            rowny = true;
                            //  } else {
                            if (maxDlugosc < dlugosc) {
                                maxDlugosc = dlugosc;
                                maxPodsuma = podsuma;

                            }
                            podsuma = poprzedniWyraz + aktualnyWyraz;
                            dlugosc = 2;
                            czyRosnacy = aktualnyWyraz > poprzedniWyraz;
                            rowny = aktualnyWyraz == poprzedniWyraz;
                            System.out.println("akt: " + aktualnyWyraz + " pop: " + poprzedniWyraz + " dlugosc: " + dlugosc + " " + 6);
                            //}
                        }
                    }
                }
                poprzedniWyraz = aktualnyWyraz;
            }
            System.out.println(maxDlugosc + " " + maxPodsuma);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//65 87 47 5 12 74 25 32 78 44 40 77 85 4 29 57:

2 个答案:

答案 0 :(得分:1)

试试这个:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Rozwiazanie {
    public static void main(String[] args) {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String[] splittedLinia = br.readLine().split((char) 32 + "");//moglaby byc " " ale tak na wszelki wypadek nie ma chuja zeby sie popierdolilo teraz nawet na linuxie
            int aktualnyWyraz = Integer.parseInt(splittedLinia[0]);//uwaga jakby cos nie gralo w sprawdzarce zmien typ na long
            int poprzedniWyraz = 0; 

            long podsumaRosnaca = aktualnyWyraz;
            long podsumaSpadajaca = aktualnyWyraz;

            int dlugoscRosnaca = 1;
            int dlugoscSpadajaca = 1;

            int maxDlugosc = 1;
            long maxPodsuma = aktualnyWyraz;

            int czyRosnacy = 0; // 0 -- nie znane (jezeli w poczatku wszystkie liczby sa rowne), 1 -- rosnacy, -1 -- spadajacy
            boolean rowny = false;
            System.out.println("akt: " + aktualnyWyraz + " dlR: " + dlugoscRosnaca + " podsumaR: " + podsumaRosnaca + " dlP: " + dlugoscSpadajaca + " podsumaP: " + podsumaSpadajaca);

            for (int i = 1; i < splittedLinia.length; i++) {
                poprzedniWyraz = aktualnyWyraz;
                aktualnyWyraz = Integer.parseInt(splittedLinia[i]);
                if (aktualnyWyraz == poprzedniWyraz) {
                    podsumaRosnaca += aktualnyWyraz;
                    podsumaSpadajaca += aktualnyWyraz;
                    dlugoscRosnaca++;
                    dlugoscSpadajaca++;
                    rowny = true;
                } else { // rozne liczby
                    if (aktualnyWyraz > poprzedniWyraz) { // rosnie
                        podsumaRosnaca += aktualnyWyraz;
                        dlugoscRosnaca++;      

                        if (rowny) {
                            dlugoscSpadajaca = 1;
                            podsumaSpadajaca = 0;
                            rowny = false;
                        }       
                        if (czyRosnacy < 0) {
                            if (dlugoscSpadajaca > maxDlugosc) {
                                maxDlugosc = dlugoscSpadajaca;
                                maxPodsuma = podsumaSpadajaca;
                            }
                            podsumaSpadajaca = 0;
                            dlugoscSpadajaca = 1;
                        }
                        czyRosnacy = 1;   
                    } else { // spada
                        podsumaSpadajaca += aktualnyWyraz;
                        dlugoscSpadajaca++; 

                        if (rowny) {
                            dlugoscRosnaca = 1;
                            podsumaRosnaca = 0;
                            rowny = false;
                        }
                        if (czyRosnacy == 1) {
                            if (dlugoscRosnaca > maxDlugosc) {
                                maxDlugosc = dlugoscRosnaca;
                                maxPodsuma = podsumaRosnaca;
                            }
                            podsumaRosnaca = 0;
                            dlugoscRosnaca = 1;
                        }  
                        czyRosnacy = -1;
                    }

                }
                System.out.println("akt: " + aktualnyWyraz + " dlR: " + dlugoscRosnaca + " podsumaR: " + podsumaRosnaca + " dlP: " + dlugoscSpadajaca + " podsumaP: " + podsumaSpadajaca);
            }


            System.out.println("maxDlugosc " + maxDlugosc + " maxPodsuma " + maxPodsuma);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我必须改变:

  • 你需要一个计数器[dlugosc](+ sum [podsuma])来升序 [rosnacy]和降序[spadajacy]值,因为你需要计算 两者都是相同的[rowny]。
  • 我改变了布尔“rowny” [等于] int,因为我认为有3个值可能: 上升,下降或未知。如果有几个相等的值 一开始,一直都是“未知”。
  • 此程序至少需要一个号码,但因此您无需每次都登记 循环的迭代是否i == 0。
  • 通过 数字,我要检查几件事,最重要的是,是否 实际值[aktualnyWyraz]和上次使用的值 [poprzedniWyraz]是相同的(然后所有的计数器和总和都必须 改变)或不同。不同可以意味着上升或下降,所以 我们必须增加相关的计数器并总结相关的总和。 “对立”变量会发生什么?好吧,我们需要检查一下 计数器大于最大值(所以这些值可能是 对结果有用)然后将它们设置回原点。

答案 1 :(得分:0)

非常简单,我试着把它写成尽可能容易理解。从我对你的代码的理解,你确实尝试了一些东西,我想我也看到了你犯的错误,但由于语言的原因,我无法确定:p

public static int monotonicSum()
{
    int maxLength = 0;
    int maxSum = 0;
    int sum = 0;
    int length = 0;
    int[] numbers = {1, 1, 7, 3, 2, 0, 0, 4, 5, 5, 6, 2, 1};

    for(int i = 0; i < numbers.length-1;i++)
    {
        if(numbers[i+1] >= numbers[i])
        {
            sum += numbers[i];
            length++;
            System.out.println(numbers[i]);
        }
        else
        {
            // Still add last numbers
            sum += numbers[i];
            length++;

            if(sum>maxSum)
                maxSum = sum;

            if(length > maxLength)
                maxLength = length;
            sum = 0;
            length = 0;
        }
    }
    System.out.println(maxLength + " sum: " + maxSum);
    return sum;
}