Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2280. Minimum Lines to Represent a Line Chart #125

Open
Woodyiiiiiii opened this issue May 22, 2022 · 0 comments
Open

2280. Minimum Lines to Represent a Line Chart #125

Woodyiiiiiii opened this issue May 22, 2022 · 0 comments

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented May 22, 2022

You are given a 2D integer array stockPrices where stockPrices[i] = [dayi, pricei] indicates the price of the stock on day dayi is pricei. A line chart is created from the array by plotting the points on an XY plane with the X-axis representing the day and the Y-axis representing the price and connecting adjacent points. One such example is shown.

...


周赛第三题。

这道题凭直觉来讲是求解有多少个斜率

如果直接从三点的斜率直接判断,即(y1 - y2) / (x1 - x2) == (y2 - y3) / (x2 - x3),使用double来存储除数,会过不了一个样例。原因是double的精度问题:double无法精确表示10的负数次方。

比如

double res = 1.0 - 0.9; 

打印出来后是0.09999999999999998。因为浮点数是二进制运算,就像十进制无法精确表示1/3一样,二进制无法对0.1除尽。

代码如下:

class Solution {
    public int minimumLines(int[][] stockPrices) {
        
        if (stockPrices.length == 1) {
            return 0;
        } else if (stockPrices.length == 2) {
            return 1;
        }

        Arrays.sort(stockPrices, Comparator.comparingInt(o -> o[0]));

        double k = (stockPrices[1][1] - stockPrices[0][1]) * 1.0 / (stockPrices[1][0] - stockPrices[0][0]);
        int cnt = 1;

        for (int i = 2; i < stockPrices.length; i++) {
            double nextK = (stockPrices[i][1] - stockPrices[i - 1][1]) * 1.0 / (stockPrices[i][0] - stockPrices[i - 1][0]);
            if (k != nextK) {
                k = nextK;
                cnt++;
            }
        }

        return cnt;
        
    }
}

这时候要想到避免出现浮点数运算,考虑用叉乘代替除法:x1y2 == x2y1。又因为单个数字较大(最大为10^9),相乘结果用long来存储,因为最大整型(Integer.MAX_VALUE)相乘也不会超过long的最大值。因为contest中不会显示错误test case,所以我还以为是我本身的算法问题而不是精度问题,也没想到叉乘,菜

class Solution {
    public int minimumLines(int[][] stockPrices) {
        
        if (stockPrices.length == 1) {
            return 0;
        } else if (stockPrices.length == 2) {
            return 1;
        }

        Arrays.sort(stockPrices, Comparator.comparingInt(o -> o[0]));
        
        int cnt = 1;
        for (int i = 2; i < stockPrices.length; i++) {
            long xDiff = stockPrices[i][0] - stockPrices[i - 1][0];
            long yDiff = stockPrices[i][1] - stockPrices[i - 1][1];
            long xxDiff = stockPrices[i][0] - stockPrices[i - 2][0];
            long yyDiff = stockPrices[i][1] - stockPrices[i - 2][1];
            if (xDiff * yyDiff != yDiff * xxDiff) {
                cnt++;
            }
        }

        return cnt;
        
    }
}

看了其他大佬的题解,还可以使用最大公约数来避免斜率除法的出现。算出最大公约数,然后判断倍数是否相等来判断斜率是否相等。

class Solution {
    public int minimumLines(int[][] stockPrices) {
        
        if (stockPrices.length == 1) {
            return 0;
        } else if (stockPrices.length == 2) {
            return 1;
        }

        Arrays.sort(stockPrices, Comparator.comparingInt(o -> o[0]));
        
        int cnt = 1;
        for (int i = 2; i < stockPrices.length; i++) {
            int x = stockPrices[i][0];
            int y = stockPrices[i][1];
            int preX = stockPrices[i - 1][0];
            int preY = stockPrices[i - 1][1];
            int ppreX = stockPrices[i - 2][0];
            int ppreY = stockPrices[i - 2][1];
            int gcd1 = gcd(y - preY, x - preX);
            int gcd2 = gcd(preY - ppreY, preX - ppreX);
            int dy1 = (y - preY) / gcd1;
            int dy2 = (preY - ppreY) / gcd2;
            int dx1 = (x - preX) / gcd1;
            int dx2 = (preX - ppreX) / gcd2;
            if (dy1 != dy2 || dx1 != dx2) {
                ++cnt;
            }
        }

        return cnt;
        
    }
    
    // 求最大公约数算法
    int gcd(int a, int b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }
    
}

reference:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant