2020-10-10 Daily-Challenge

Today is Saturday, I gonna review the tasks I've done this week, and finish today's leetcode's October LeetCoding Challenge with cpp.

LeetCode Review

Range Sum Query - Mutable

rewrite it with segment tree

class NumArray {
  vector<int> val;
  vector<int> lazy;
  int operation_begin;
  int operation_end;
  int size;
  void build(vector<int>& nums, int root_index, int begin, int end) {
    if(begin == end) {
      val[root_index] = nums[begin];
    } else {
      int mid = (begin + end) >> 1;
      build(nums, root_index*2+1, begin, mid);
      build(nums, root_index*2+2, mid+1, end);
      val[root_index] = val[root_index*2+1] + val[root_index*2+2];
    }
  }
  void pushdown(int root_index, int count) {
    if(lazy[root_index]) {
      val[root_index*2+1] += (count - count/2)*lazy[root_index];
      val[root_index*2+2] += (count/2)*lazy[root_index];
      lazy[root_index*2+1] += lazy[root_index];
      lazy[root_index*2+2] += lazy[root_index];
      lazy[root_index] = 0;
    }
  }
  void update(int root_index, int begin, int end, int difference) {
    if(operation_begin <= begin && operation_end >= end) {
      val[root_index] += difference * (operation_end-operation_begin+1);
      lazy[root_index] += difference;
      return;
    }
    pushdown(root_index, end-begin+1);
    int mid = (end + begin) >> 1;
    if(operation_begin <= mid) update(root_index*2+1, begin, mid, difference);
    if(operation_end > mid) update(root_index*2+2, mid+1, end, difference);
    val[root_index] = val[root_index*2+1] + val[root_index*2+2];
  }
  int query(int root_index, int begin, int end) {
    if(operation_begin <= begin && operation_end >= end) {
      return val[root_index];
    }
    pushdown(root_index, end-begin+1);
    int ans = 0;
    int mid = (begin + end) >> 1;
    if(operation_begin <= mid) ans += query(root_index*2+1, begin, mid);
    if(operation_end > mid) ans += query(root_index*2+2, mid+1, end);
    return ans;
  }
public:
  NumArray(vector<int>& nums) {
    val = vector<int>(nums.size()*4);
    lazy = vector<int>(nums.size()*4);
    size = nums.size()-1;
    if(size == 0) return;
    build(nums, 0, 0, size);
  }
  
  void update(int i, int val) {
    operation_begin = i;
    operation_end = i;
    int diff = val - query(0, 0, size);
    update(0, 0, size, diff);
  }
  
  int sumRange(int i, int j) {
    operation_begin = i;
    operation_end = j;
    return query(0, 0, size);
  }
};

Complement of Base 10 Integer

not using built-in function

class Solution {
public:
  int bitwiseComplement(int N) {
    int val = 1;
    while(val <= N) {
      val <<= 1;
    }
    // same with (val-1|1)-N
    return N^(val-1 | 1);
  }
};

Distribute Candies to People

seems not change much

class Solution {
public:
  vector<int> distributeCandies(int candies, int num_people) {
    vector<int> answer = vector<int>(num_people, 0);
    long long start = 0, end = candies;
    while(start < end) {
      long long mid = (start + end) >> 1;
      if(mid*(1+mid) / 2 >= candies) {
        end = mid;
      } else {
        start = mid + 1;
      }
    }
    int last_index = end-1;
    int rounds = last_index / num_people;
    int remain = last_index % num_people;
    for(int i = 0; i < num_people; ++i) {
      answer[i] = (i+1) * (last_index/num_people) + num_people*(rounds-1)*rounds/2;
      if(i < remain) {
        answer[i] += i+1 + rounds*num_people;
      }
    }
    answer[remain] += candies - last_index*(last_index+1)/2;
    return answer;
  }
};

Insert into a Binary Search Tree

more elegant code

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(!root) return new TreeNode(val);
        if(val > root->val) root->right = insertIntoBST(root->right, val);
        else root->left = insertIntoBST(root->left, val);
        return root;
    }
};

Data Stream as Disjoint Intervals

I need more practice

and this solution runs slower

class SummaryRanges {
  set<pair<int, int>> m;
public:
  void addNum(int val) {
    auto it = m.lower_bound(make_pair(val, val));
    int new_begin = val, new_end = val;
    if(it != m.begin() && ((--it)->second+1 < val)) ++it;
    while(it != m.end() && val+1 >= it->first && val-1 <= it->second) {
      new_begin = min(new_begin, it->first);
      new_end = max(new_end, it->second);
      it = m.erase(it);
    }
    m.insert(make_pair(new_begin, new_end));
  }
  
  vector<vector<int>> getIntervals() {
    vector<vector<int>> ans;
    vector<int> tmp;
    for(auto it = m.begin(); it != m.end(); ++it) {
      tmp.push_back(it->first);
      tmp.push_back(it->second);
      ans.push_back(tmp);
      tmp.clear();
    }
    return ans;
  }
};

Rotate List

nothing to say

class Solution {
    int length(ListNode* head) {
        ListNode *cur = head;
        int len = 0;
        while(cur) {
            cur = cur->next;
            len += 1;
        }
        return len;
    }
public:
    ListNode* rotateRight(ListNode* head, int k) {
        int len = length(head);
        if(!len || k%len == 0) return head;
        k = len-(k%len);
        cout << k << endl;
        ListNode *cur = head, *previous;
        while(k--) {
            previous = cur;
            cur = cur->next;
        }
        ListNode *new_head = cur;
        while(cur->next) cur = cur->next;
        cur->next = head;
        previous->next = NULL;
        return new_head;
    }
};

October LeetCoding Challenge 10

Description

Minimum Number of Arrows to Burst Balloons

There are some spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it's horizontal, y-coordinates don't matter, and hence the x-coordinates of start and end of the diameter suffice. The start is always smaller than the end.

An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps traveling up infinitely.

Given an array points where points[i] = [xstart, xend], return the minimum number of arrows that must be shot to burst all balloons.

Example 1:

Input: points = [[10,16],[2,8],[1,6],[7,12]]
Output: 2
Explanation: One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).

Example 2:

Input: points = [[1,2],[3,4],[5,6],[7,8]]
Output: 4

Example 3:

Input: points = [[1,2],[2,3],[3,4],[4,5]]
Output: 2

Example 4:

Input: points = [[1,2]]
Output: 1

Example 5:

Input: points = [[2,3],[2,3]]
Output: 1

Constraints:

  • 0 <= points.length <= 104
  • points.length == 2
  • -231 <= xstart < xend <= 231 - 1

Solution

simple greedy

class Solution {
public:
  int findMinArrowShots(vector<vector<int>>& points) {
    sort(points.begin(), points.end());
    int cnt = 0, min_end = -1;
    bool hasBalloon = false;
    for(int i = 0; i < points.size(); ++i) {
      if(!hasBalloon) {
        min_end = points[i][1];
        hasBalloon = true;
      } else {
        if(points[i][0] > min_end) {
          cnt += 1;
          hasBalloon = true;
          min_end = points[i][1];
        } else {
          min_end = min(points[i][1], min_end);
        }
      }
    }
    if(hasBalloon) cnt += 1;
    return cnt;
  }
};