Leetcode Contest 77 解題小結

原題鏈接:https://leetcode.com/contest/weekly-contest-77

本週感覺難度不大….三道模擬,一道 DP。

Number of Lines To Write String

給定一個字符寬度數組 width[a..z],一個字符串 S。打印字符串,每行寬度限制爲100,不能截斷字符(換行)。

  1. 能打多少行
  2. 最後一行的打印寬度

模擬。

  1. 將 A 看成首尾相接循環串,每次以 A[i] 字符爲開頭,截取其中長度爲 A.length 的子串,與 B 進行對比,如果匹配則返回 True,直到所有子串都輪詢一遍仍沒有匹配的子串則返回 False。

    // Time Complexity O(len(S))
    class Solution {
       public int[] numberOfLines(int[] widths, String S) {
           char[] temp = S.toCharArray();
    
           int line = 1, linew = 0;
           for (char c : temp) {
               int x = (int) (c - 'a');
               if (linew + widths[x] > 100) {
                   line++;
                   linew = widths[x];
               } else {
                   linew += widths[x];
               }
           }
           return new int[]{line, linew};
       }
    }

Unique Morse Code Words

給定一個字符 -> Morse Code 映射 String[a..z],一個字符串數組 words[],將所有字符串翻譯成對應的 Morse Code 串,求不同串的數目。

模擬。

  1. 轉換字符串 -> insert in HashSet -> return HashSet.size()

    // Time Complexity O(∑len(word))
    class Solution {
       public int uniqueMorseRepresentations(String[] words) {
           String[] code = new String[]{".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
           Set<String> set = new HashSet<>();
    
           for (String word: words) {
               String res = trans(word, code);
               set.add(res);
           }
    
           return set.size();
       }
    
       String trans(String word, String[] code) {
           StringBuilder res = new StringBuilder();
           for (char c: word.toCharArray()) {
               res.append(code[c - 'a']);
           }
           return res.toString();
       }
    }

Max Increase to Keep City Skyline

給定一個 grid[][] 矩陣,grid[i][j]代表 (i,j) 建築物的高度,我們可以增加任意建築物的高度,但保持上下左右四個視圖與原建築矩陣相同,求所有建築物最多能增加多少高度(與原矩陣的高度差)。

Example:
Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]
Output: 35

Explanation: 
The grid is:
[ [3, 0, 8, 4], 
  [2, 4, 5, 7],
  [9, 2, 6, 3],
  [0, 3, 1, 0] ]
gridNew = [ [8, 4, 8, 7],
            [7, 4, 7, 7],
            [9, 4, 8, 7],
            [3, 3, 3, 3] ]

模擬。

  1. 求行列最大高度,grid_new[i][j]爲兩者取 min,這樣不會影響視圖且最優。

    // Time Complexity O(n^2)
    class Solution {
       public int maxIncreaseKeepingSkyline(int[][] grid) {
           int ans = 0;
           if (grid.length == 0 || grid[0].length == 0) return ans;
    
           int[] maxrow = new int[grid.length];
           int[] maxcol = new int[grid[0].length];
    
           for (int i = 0; i < grid.length; i++) {
               for (int j = 0; j < grid[0].length; j++) {
                   maxrow[i] = Math.max(maxrow[i], grid[i][j]);
                   maxcol[j] = Math.max(maxcol[j], grid[i][j]);
               }
           }
    
           for (int i = 0; i < grid.length; i++) {
               for (int j = 0; j < grid[0].length; j++) {
                   ans += Math.min(maxrow[i], maxcol[j]) - grid[i][j];
               }
           }
    
           return ans;
       }
    }

Split Array With Same Average

給一個 int 序列 A[],每個元素可以選擇放到兩個初始爲空的序列 B 或 C 中,全部元素都必須放到 B 或 C 中。能否找到一種分割策略,使 B 和 C 的平均值相同。

Example :
Input: 
[1,2,3,4,5,6,7,8]
Output: true
Explanation: We can split the array into [1,4,5,8] and [2,3,6,7], and both of them have the average of 4.5.

Note:

  • The length of A will be in the range [1, 30].
  • A[i] will be in the range of [0, 10000].

DP

English explanation.

我一開始想到的是 dp,用 f[t][j] = true 代表子序列可以湊出 avg=tj 。已知 f[t][j]的情況下,我們假設 A 可以分成兩個序列 B, C,長度爲 lb + lc = la,那麼 B, C 滿足一些性質:

  1. avg=Ala=Blb=Clc 三個序列的平均值均相等。avg 是已知的,那麼 B=avglb,C=avglcB,CN .

這就十分 nice,那麼我可以枚舉 lb[1,A.length1] ,通過 lb 可以求出 B, C, lc,判斷 f[B][lb] && f[C][lc] 是否爲 True,如果是,那麼表示假設成立。

問題來了,B、C 是否不相交呢?注意,因爲可以有重複的元素存在,相交是指包含相同的元素而不是相同值的元素,[1,2,2,3] -> [1,2],[2,3] 不相交,而[1,2,2,3] -> [1,2,2],[2,3] 則相交。

假設 B、C 是相交的,相交子集爲 K。

那麼

avg=Ala=B+CKlb+lclkBlb=Clc=AlaB+CKlb+lclkBlb=0Blb+ClbKlbBlbBlc+Blk(lb+lclk)lb=BlkKlb(lb+lclk)lbBlb=KlkBKlblk=Blb=avg

以上證明,說明將子集 K 從 B 中剝離出去得到 B-K,其平均值也是 avg,那麼我們仍然可以得到兩個不相交的子序列。

那麼這個方法是可行的。

// Time Complexity O(n^2 * sum)
class Solution {
    public boolean splitArraySameAverage(int[] A) {
        if (A.length <= 1) return false;
        int sum = 0;
        for (int aA : A) sum += aA;

        boolean[][] f = new boolean[sum+1][A.length+1];
        f[0][0] = true;

        for (int i = 0; i < A.length; i++) {
            for (int t = sum; t >= A[i]; t--) {
                for (int j = 1; j <= i+1; j++) {
                    f[t][j] = f[t][j] | f[t-A[i]][j-1];
                }
            }
        }

        for (int i = 1; i <= A.length / 2; i++) {
            if (sum * i % A.length == 0) {
                int b = sum * i / A.length;
                if (f[b][i]) return true;
            }
        }

        return false;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章