1. 程式人生 > >LeetCode:二進位制手錶【401】

LeetCode:二進位制手錶【401】

LeetCode:二進位制手錶【401】

題目描述

二進位制手錶頂部有 4 個 LED 代表小時(0-11),底部的 6 個 LED 代表分鐘(0-59)。

每個 LED 代表一個 0 或 1,最低位在右側。

例如,上面的二進位制手錶讀取 “3:25”。

給定一個非負整數 代表當前 LED 亮著的數量,返回所有可能的時間。

案例:

輸入: n = 1
返回: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]

 

注意事項:

  • 輸出的順序沒有要求。
  • 小時不會以零開頭,比如 “01:00” 是不允許的,應為 “1:00”。
  • 分鐘必須由兩位陣列成,可能會以零開頭,比如 “10:2” 是無效的,應為 “10:02”。

題目分析

  這道題目標註為簡單題,但感覺做起來比較費勁,雖然最後寫出來了,但感覺程式碼很冗餘。討論有很多非常巧妙的辦法,需要運用數學方法,我是絕對想不出來的。

  我的思路是這樣的,題目意思是在小時陣列{1,2,4,8} 和分鐘陣列{1,2,4,8,16,32}中一共選擇N個數來組成一個時間

  那我們第一個要解決的問題是如何在一個數組中選出所有N個數的組合

  1、如何取出組合的第一個數?

  我們從左往右,首先我們將a加入tmpList(臨時儲存排列的線性表)中,此後再從它下一個位置開始找第二個、第三個數字,最後生成排列儲存在結果中。我們再將1作為第一個元素開始處理後,趕緊把他刪了,再將b加入到tmpList中,此後再從它下一個位置開始找第二個、第三個數字,最後生成排列儲存在結果中....

  也就是說處理第i個位置的元素時,就要考慮到i位置的所有取值,我們在處理為a的元素後,趕緊把他刪了處理為b的元素.....這樣第i個位置就有所有的情況了

  

  知道這個以後,我們就可以得到在一個數組中選出所有N個數的組合。

  2、關於排列組合的一個典型的遞歸回溯框架是這樣的

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
   if(tempList.size() == nums.length){
      list.add(new ArrayList<>(tempList));
   } else{
      for(int i = 0; i < nums.length; i++){
         if(tempList.contains(nums[i])) continue; // element already exists, skip
         tempList.add(nums[i]);
         backtrack(list, tempList, nums);
         tempList.remove(tempList.size() - 1);
      }
   }
}

  當我們分別取出小時和分鐘的各種可能情況,再次做他們的笛卡爾積,從而生產所有的時間可能。  

  很抱歉的是,這道題並不需要嚴格的遞歸回溯框架,我從而使用了簡單使用了深搜。

    /**
     * 
     * @param arr  待產生排列的陣列
     * @param index 位置下標
     * @param cur   已經找了CUR個數
     * @param n     一共要找N個數
     * @param val   已經找到的數的和
     * @param res   當招夠N個數後把他加入res表中
     * @param max   val不能超過多少
     */
    private  void helper(int[] arr,int index,int cur,int n,int val,List<Integer> res,int max)
    {
        if(cur>n)
            return;
        if(cur==n&&val<max)
            res.add(val);
        for(int i =index;i<arr.length;i++) {
            helper(arr, i+1,cur+1, n, val + arr[i],res,max);
        }
    }

Java題解

class Solution {
    public List<String> readBinaryWatch(int num) {
        int[] hour = {1,2,4,8};
        int[] minute ={1,2,4,8,16,32};
        List<Integer> hourList = new ArrayList<>();
        List<Integer> minuteList = new ArrayList<>();
        List<String>  ans  = new ArrayList<>();
        for(int i=0;i<=num;i++)
        {
            helper(hour,0,0,i,0,hourList,12);
            helper(minute,0,0,num-i,0,minuteList,60);
            for(int hi = 0;hi<hourList.size();hi++)
                for(int mi =0;mi<minuteList.size();mi++)
                {
                    String minVal = String.valueOf(minuteList.get(mi));
                    if(minVal.length()<2)
                        minVal = "0"+minVal;
                    ans.add(hourList.get(hi)+":"+minVal);
                }
            hourList = new ArrayList<>();
            minuteList = new ArrayList<>();
        }
        Collections.sort(ans);
        return ans;
    }


    private  void helper(int[] arr,int index,int cur,int n,int val,List<Integer> res,int max)
    {
        if(cur>n)
            return;
        if(cur==n&&val<max)
            res.add(val);
        for(int i =index;i<arr.length;i++) {
            helper(arr, i+1,cur+1, n, val + arr[i],res,max);
        }
    }

}