LeetCode 279 Perfect Squares (BFS 优化 or 数学)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tc_To_Top/article/details/88803380

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

Example 1:

Input: n = 12

Output: 3 
Explanation: 12 = 4 + 4 + 4.

Example 2:

Input: n = 13

Output: 2
Explanation: 13 = 4 + 9.

题目链接:https://leetcode.com/problems/perfect-squares/

题目分析:先暴力BFS一发:101ms,时间击败20%

class Solution {
    
    class Item {
        int num, step;
        Item(int num, int step) {
            this.num = num;
            this.step = step;
        }
    }
    
    public int numSquares(int n) {
        HashSet<Integer> st = new HashSet<>();
        Queue<Item> q = new LinkedList<>();
        q.offer(new Item(n, 0));
        st.add(n);
        while (!q.isEmpty()) {
            Item cur = q.poll();
            if (cur.num == 0) {
                return cur.step;
            }
            int ma = (int)Math.sqrt(1.0 * cur.num);
            for (int i = ma; i >= 1; i--) {
                Item item = new Item(cur.num - i * i, cur.step + 1);
                if (!st.contains(item.num)) {
                    st.add(item.num);
                    q.offer(item);
                }
            }
        }
        return n;
    }
}

把HashSet改成数组:34ms,时间击败45%

class Solution {
    
    class Item {
        int num, step;
        Item(int num, int step) {
            this.num = num;
            this.step = step;
        }
    }
    
    public int numSquares(int n) {
        boolean[] vis = new boolean[n + 1];
        Queue<Item> q = new LinkedList<>();
        q.offer(new Item(n, 0));
        vis[n] = true;
        while (!q.isEmpty()) {
            Item cur = q.poll();
            if (cur.num == 0) {
                return cur.step;
            }
            int ma = (int)Math.sqrt(1.0 * cur.num);
            for (int i = ma; i >= 1; i--) {
                Item item = new Item(cur.num - i * i, cur.step + 1);
                if (!vis[item.num]) {
                    vis[item.num] = true;
                    q.offer(item);
                }
            }
        }
        return n;
    }
}

把class Item改成int[]:19ms,时间击败87.2%

BFS的时候如果正着搜是26ms,尽管sqrt是个比较耗时的函数,但是就本题而言,优先减大的可以更快得到解

class Solution {
    
    public int numSquares(int n) {
        boolean[] vis = new boolean[n + 1];
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[]{n, 0});
        vis[n] = true;
        while (!q.isEmpty()) {
            int[] cur = q.poll();
            if (cur[0] == 0) {
                return cur[1];
            }
            int ma = (int)Math.sqrt(1.0 * cur[0]);
            for (int i = ma; i >= 1; i--) {
                int nxtVal = cur[0] - i * i;
                if (nxtVal >= 0 && !vis[nxtVal]) {
                    vis[nxtVal] = true;
                    q.offer(new int[]{nxtVal, cur[1] + 1});
                }
            }
        }
        return n;
    }
}

在offer之前判断nxtVal是否为0,减少一层搜索:7ms,时间击败97.9%

class Solution {
    
    public int numSquares(int n) {
        boolean[] vis = new boolean[n + 1];
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[]{n, 0});
        vis[n] = true;
        while (!q.isEmpty()) {
            int[] cur = q.poll();
            int ma = (int)Math.sqrt(1.0 * cur[0]);
            for (int i = ma; i >= 1; i--) {
                int nxtVal = cur[0] - i * i;
                if (nxtVal == 0) {
                    return cur[1] + 1;
                }
                if (!vis[nxtVal]) {
                    vis[nxtVal] = true;
                    q.offer(new int[]{nxtVal, cur[1] + 1});
                }
            }
        }
        return n;
    }
}

最优解是采用拉格朗日四平方和定理:0ms,时间击败100%

参考:https://en.wikipedia.org/wiki/Lagrange%27s_four-square_theorem

class Solution {
    
    public int numSquares(int n) {
        while (n % 4 == 0) {
            n >>= 2;
        }
        if (n % 8 == 7) {
            return 4;
        }
        for (int x = 0; x * x <= n; x++) {
            int y = (int)Math.sqrt(n - x * x);
            if (x * x + y * y == n) {
                return 1 + (x == 0 ? 0 : 1);
            }
        }
        return 3;
    }
}

猜你喜欢

转载自blog.csdn.net/Tc_To_Top/article/details/88803380