1. 程式人生 > >Leet.473火柴拼正方形(Matchsticks to Square)

Leet.473火柴拼正方形(Matchsticks to Square)

思路:

這道題的相對難點在於求得邊長後  可能有很多條火柴來構成這條邊 而被使用的火柴不能再次使用

若某次使用了某一根火柴  則可能導致另一條本能夠湊成的邊無法湊得 所以需要回溯到上一次選擇

看到這裡

首先想到(只想到)的方法是用DFS來實現

可以說是一個經典的DFS問題型別了

步驟是常見的建立對應的visit陣列來對應每條火柴是否使用 嘗試每一種選擇 若走到死路則回溯到上一節點 visit還原 直到四條邊均湊成或者是嘗試了所有搭配均失敗

這道題由於提到“火柴陣列的長度不超過15”

所以可以有一些很好想到的剪枝方法

如果總長度不是4的整數倍/某條邊的長度大於理論邊長/陣列長度為0這樣直接返回false

初次進入dfs的邊數為4 index對於的是當前嘗試使用的是第幾根火柴 sumnow是目前在湊的這條邊已經使用的火柴的長度和

class Solution 
{
static boolean dfs(int[] nums,boolean[] visit,int bianchang,int index,int sumnow,int bian)
    {
        if(bian==1)//成功條件 
        {
            return true;
        }
        else if(sumnow>bianchang)//當前和大於邊長
        {
            return false;
        }
        else if(sumnow==bianchang)//某條邊完成 邊數-1
        {
            return dfs(nums,visit,bianchang,0,0,bian-1);
        }
        else
        {
            for(int i=index;i<nums.length;i++)
            {
                if(visit[i]==false)
                {
                    visit[i]=true;
                    if(dfs(nums,visit,bianchang,i+1,sumnow+nums[i],bian))
                    {
                        return true;
                    }
                    visit[i]=false;
                }
            }
            return false;
        }
    }
    public boolean makesquare(int[] nums) 
    {
        int totallength=0;
        if(nums.length==0)
        {
            return false;
        }
        for(int i=0;i<nums.length;i++)
        {
            totallength+=nums[i];
        }
        int bianchang=totallength/4;
        if(totallength%4!=0)
        {
            return false;
        }
        for(int i=nums.length-1;i>=0;i--)
        {
            if(nums[i]>bianchang)
            {
                return false;
            }
        }
        boolean visit[]=new boolean[nums.length];
        return dfs(nums,visit,bianchang,0,0,4);
    }    
}