1. 程式人生 > >leetcode 279-Perfect Squares(medium)

leetcode 279-Perfect Squares(medium)

是否 ins amp fir tco -i ... n) true

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

1. DP

Set an array, first initiate index=i^2 with 1.

Then calculate others with dp[j]=Math.min(dp[j],dp[j-i*i]+dp[i*i]) //註意,這裏在自己第一次寫的時候,最後一項寫成了dp[i],要仔細!前面更新的是dp[i*i]為1,而不是dp[i]為1。

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

2. BFS

按照bfs的思想,每輪依次入隊需要1,2,3,……步到達的點,如果遇到n則直接返回這一輪對應的步數。

自己寫的第一版。註意queue的size是會變的,一開始寫的時候還出了低級錯誤,沒有把queue的size先取出來然後在一輪循環中固定不變,而是直接寫了queue.size(),忽視了這個量每個循環下來都會變的。以下這種方法會MLE,主要是在入隊的時候沒有判斷這個數是否已經入隊過,如果已經入隊過就不需要再入隊了,我們只關心一個數最小的組成成分個數,即到達該數最小的步數。(其實寫的時候已經註意到了入隊的元素會有重復,但都竟然沒想到用一個set去避免,對數據結構的運用還是太不熟悉啊)

class Solution {
    public int numSquares(int n) {
        //bfs
        if(n==0) return 0;
        int sr=(int)Math.sqrt(n);
        Queue<Integer> queue=new LinkedList<>();
        queue.offer(0);
        int count=0;
        while(true){
            count++;
            int s=queue.size();
            for(int j=0;j<s;j++){
                int num=queue.poll();
                for(int i=1;i<=sr;i++){
                    if(num+i*i==n) return count;
                    if(num+i*i>n) continue;
                    queue.offer(num+i*i);
                }
            }
        }
    }
}

改進後:(加入set visited來記錄是否入隊過)(s-->0這種寫法比較簡潔)

class Solution {
    public int numSquares(int n) {
        //bfs
        if(n==0) return 0;
        int sr=(int)Math.sqrt(n);
        Queue<Integer> queue=new LinkedList<>();
        queue.offer(0);
        Set<Integer> visited=new HashSet<>();
        int count=0;
        while(true){
            count++;
            int s=queue.size();
            while(s-->0){
                int num=queue.poll();
                for(int i=1;i<=sr;i++){
                    if(num+i*i==n) return count;
                    if(num+i*i>n) break;//第一次寫的時候寫成了continue,當大於n的時候,後面的就不需要再考慮了,所以應該直接break
                    if(!visited.contains(num+i*i)){
                        queue.offer(num+i*i);
                        visited.add(num+i*i);
                    }
                }
            }
        }
    }
}

leetcode 279-Perfect Squares(medium)