279. Perfect Squares


題目:

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

For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.

鏈接: http://leetcode.com/problems/perfect-squares/

題解:

又是數學題,每次一看jianchao.li.fighter添加的題目,就知道跟數字有關系。數學不好的我,做起來真的很頭大....這道題看了discuss以后發現有好多種方法,有dp, BFS,還有純數學解法。下面是最簡單的dp,核心的遞推公式是對於j= 1 , j * j <= i來說, tmp = Math.min(tmp, tmp[i - j * j] + 1);

Time Complexity - O(nlogn), Space Complexity - O(n)

public class Solution {
    public int numSquares(int n) {
        if(n < 1) {
            return 0;
        }
        int[] min = new int[n + 1];
        
        for(int i = 1; i <= n; i++) {
            int tmp = Integer.MAX_VALUE;
            for(int j = 1; j * j <= i; j++) {
                tmp = Math.min(tmp, min[i - j * j] + 1);
            }
            min[i] = tmp;
        }
        
        return min[n];
    }
}

 

題外話:

最近似乎喪失了獨立思考的能力,每次做題想了5分鍾就不耐煩去看Discuss的答案了。這樣可不行,需要鍛煉的不是記題背題,而是自己的思維。真是懶惰到家了。

 

 

二刷:

依然是使用和一刷一樣的方法。

我們主要就是建立一個dp數組。在i從1到n的過程中,我們計算 dp[i - j * j] + 1最小的值。也就是減去一個平方數后我們比較這個剩余值的最小值,再加上1,就是我們的dp[i]

Java:

Time Complexity - O(n * sqrt(n)), Space Complexity - O(n)

 

public class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            int min = n;
            for (int j = 1; j * j <= i; j++) {
                min = Math.min(min, dp[i - j * j] + 1);
            }
            dp[i] = min;
        }
        return dp[n];
    }
}

 

三刷:

又卡了這道題,不過現在找到了原因 - 直覺上總覺得除了DP以外會有更好的解法,事實上也確實有很好的數學解法。有機會再好好理解,現在要做到的是,碰到題目,至少要能夠想出一個可行的解法,再考慮優化。

數學解法就是拉格朗日了,意思是說每個自然數都可以被表示為4個自然數的平方。先mark下來,以后再看。  https://en.wikipedia.org/wiki/Lagrange%27s_four-square_theorem

Java: 

DP:

public class Solution {
    public int numSquares(int n) {
        if (n < 1) return n;
        int[] dp = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            int min = Integer.MAX_VALUE;
            for (int j = 1; j * j <= i; j++) {
                min = Math.min(min, dp[i - j * j] + 1);
            }
            dp[i] = min;
        }
        return dp[n];
    }
}

 

題外話:

一道題目做了好幾遍還會卡,說明並不理解。需要真正好好靜下心來思考才行。

 

Reference:

https://leetcode.com/discuss/58056/summary-of-different-solutions-bfs-static-and-mathematics

https://leetcode.com/discuss/56982/o-sqrt-n-in-ruby-c-c

https://leetcode.com/discuss/62526/an-easy-understanding-dp-solution-in-java

https://leetcode.com/discuss/56983/simple-java-dp-solution

https://leetcode.com/discuss/72205/java-dp-solution-with-explanation

https://leetcode.com/discuss/57066/4ms-c-code-solve-it-mathematically

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

https://www.alpertron.com.ar/4SQUARES.HTM

https://leetcode.com/discuss/57185/o-sqrt-n-about-0-034-ms-and-0-018-ms

https://leetcode.com/discuss/93109/straightforward-java-bfs-beats-93-69%25

https://leetcode.com/discuss/57850/explanation-of-the-dp-solution

https://leetcode.com/discuss/68295/beautiful-9-lines-java-solution

https://leetcode.com/discuss/57020/java-solution-o-n-1-2-time-and-o-1-space

https://leetcode.com/discuss/57477/sqrt-applying-fermats-theorm-brahmagupta-fibonacci-identity

https://leetcode.com/discuss/63750/concise-java-dp-solution

https://en.wikipedia.org/wiki/Fermat%27s_theorem_on_sums_of_two_squares


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM