## LeetCode Contest #54

**697. Degree of an Array**

**题目：** 给定一个数组，定义这个数组的degree是数组中某一个数字出现次数的最大值。

`        degree of arr  :=  max_i arr.count(arr[i])`

求最短的一个continuous subarray，使得这个subarray的degree跟原数组相同。返回这个subarray的长度。

**题解：** 思路很简单，先把出现次数最多的数挑出来，然后看这些数在原数组中的“跨度”。

```cpp
class Solution {
    map<int, int> cnt, left, right;
    /* left, right is used to record the*/
    /* left most position and right most position*/
    /* of a particular element.*/
public:
    int findShortestSubArray(vector<int>& nums) {
        for(int i=0;i<nums.size();++i){
            cnt[nums[i]]++;
            right[nums[i]] = i;
            if(!left.count(nums[i])) left[nums[i]] = i;
        }
        int ans = nums.size(), max_cnt = 0;
        for(auto p:cnt){
            if(p.second == max_cnt)
                ans = min(ans, right[p.first] - left[p.first] + 1);
            else if(p.second > max_cnt){
                max_cnt = p.second;
                ans = right[p.first] - left[p.first] + 1;
            }
        }
        return ans;
    }
};
```

**696. Count Binary Substrings**

**题目：** 给定一个指包括0和1的string，让你从中挑出满足以下条件的substring：

- 0跟1的个数相同
- 0都group together，1也都group together

也就是这种形式的substring：11…100…0或00…011…1，且其中1，0个数相等。

求这种substring的总数。

**题解：** 思路很简单，先把groups of continuous 1和0全提出来，然后这样的substring肯定出现在相邻的groups里面，个数就是min(#group1, #group0)。比如111跟0000相临，那满足条件的substring只可能是10, 1100, 111000，它们的个数就是1的个数，因为1比0少。

```cpp
class Solution {
    inline char flip(char c){return c=='1'? '0':'1';}
    /* input '1' return '0', input '0' return '1';*/
public:
    int countBinarySubstrings(string s) {
        int ans = 0;
        for(auto i=s.find(s[0]); i<s.size() && i!=string::npos ;){
            auto j = s.find(flip(s[i]),i);
            if(j == string::npos) return ans;
            auto k = s.find(s[i], j);
            if(k == string::npos) k = s.size();
            ans += min(int(j-i), int(k-j));
            i = j;
        }
        return ans;
    }
};
```

**698. Partition to K Equal Sum Subsets**

**题目：** 给定一个数组，数组长度不超过16（也就是说规模很小），然后让你判断是否可以把这个数组分成k个groups，使得每个group的和相等。

**题解：** 其实是暴力，（反正我是这么做的，如果有人有更好的方法，非常欢迎提出来。）因为规模不大。

- 首先如果这个数组的sum不能被k整除，就不用考虑了。
- 如果可以整除，我的做法是分两步：
    - 先求所有的group使得每个group的和是sum／k，用dfs
    - 每一个group用一个二进制数表示，这样后面的操作容易些。
    - 看这些groups能不能挑出k两个不相交的，还是用dfs
- 两个dfs都没超时，也是挺不容易的。
- 上面做法，有个地方要注意一下：判断两个group是否相交的时候，如果用(group1 & group2) == 0括号不能省啊。开始就是由于这个原因，我debug的时候半天不知道错在哪儿，后来索性改成!(group1 & group2)。

```cpp
class Solution {
    vector<int> A, G;
    void dfs1(int cur, int i, int target){
        if(target == 0){
            G.push_back(cur);
            return;
        }
        for(int j=i;j<A.size();++j) if(target>=A[j]){
            dfs1(cur|(1<<j), j+1, target-A[j]);
        }
    }
    bool dfs2(int cur, int rest){
        if(!rest) return true;
        for(auto s:G) if(!(s&cur) && dfs2(cur|s, rest-1)) return true;
        return false;
    }
public:
    bool canPartitionKSubsets(vector<int>& nums, int k) {
        A.assign(nums.begin(),nums.end());
        int sum = 0;
        for(auto n:nums) sum+=n;
        if(!sum || k<=1) return true;
        if( sum%k ) return false;
        dfs1(0, 0, sum/k);
        return dfs2(0, k-1);
    }
};
```

**699. Falling Squares**

**题目：** 其实就是模拟俄罗斯方块，而且每个方块都是正方形。一系列方块由一个pair的数组给出，且对于每一个pair，第一个元素是正方形left edge的位置，第二个元素是边长。方块依次落下，要求输出一个数组，每个元素对应每一个方块落下之后的最大高度。

**题解：** 用一个map(sorted)来标记现有每个线段的高度：map<int, int> H，这样H[pos]表示pos右边的高度。知道碰到下一个比pos大，而且也在H中的元素，也就是高度改变的点。初始的时候令H[0] = H[2E8] = 0，其实是方便以后操作；然后每次加入一个方块后，更新这个H即可，不难写：

```cpp
class Solution {
    map<int, int> H;
    int upd(const pair<int, int> &S){
        /*return the final height of the current falling square*/
        int l = S.first, h = S.second, r = S.first + S.second;
        auto it1 = --H.upper_bound(l), it2 = --H.upper_bound(r);
        int max_H = h + it1->second, tail_H = it2->second;
        ++it1;
        while(it1!=H.end() && it1->first < r){
            max_H = max(max_H, h + it1->second);
            it1 = H.erase(it1);
        }
        H[r] = tail_H;
        return H[l] = max_H;
    }
public:
    vector<int> fallingSquares(vector<pair<int, int>>& positions) {
        vector<int> ans;
        H[0] = H[2E8] = 0;
        int cur = 0;
        for(auto S:positions) ans.push_back(cur = max(cur, upd(S)));
        return ans;
    }
};
```
