<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>sweep line Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/sweep-line/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/sweep-line/</link>
	<description></description>
	<lastBuildDate>Fri, 29 Apr 2022 04:26:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.8</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>sweep line Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/sweep-line/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2251. Number of Flowers in Full Bloom</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 28 Apr 2022 05:10:51 +0000</pubDate>
				<category><![CDATA[Tree]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[sweep line]]></category>
		<category><![CDATA[treemap]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9692</guid>

					<description><![CDATA[<p>You are given a&#160;0-indexed&#160;2D integer array&#160;flowers, where&#160;flowers[i] = [starti, endi]&#160;means the&#160;ith&#160;flower will be in&#160;full bloom&#160;from&#160;starti&#160;to&#160;endi&#160;(inclusive). You are also given a&#160;0-indexed&#160;integer array&#160;persons&#160;of size&#160;n, where&#160;persons[i]&#160;is the time&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/">花花酱 LeetCode 2251. Number of Flowers in Full Bloom</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;2D integer array&nbsp;<code>flowers</code>, where&nbsp;<code>flowers[i] = [start<sub>i</sub>, end<sub>i</sub>]</code>&nbsp;means the&nbsp;<code>i<sup>th</sup></code>&nbsp;flower will be in&nbsp;<strong>full bloom</strong>&nbsp;from&nbsp;<code>start<sub>i</sub></code>&nbsp;to&nbsp;<code>end<sub>i</sub></code>&nbsp;(<strong>inclusive</strong>). You are also given a&nbsp;<strong>0-indexed</strong>&nbsp;integer array&nbsp;<code>persons</code>&nbsp;of size&nbsp;<code>n</code>, where&nbsp;<code>persons[i]</code>&nbsp;is the time that the&nbsp;<code>i<sup>th</sup></code>&nbsp;person will arrive to see the flowers.</p>



<p>Return&nbsp;<em>an integer array&nbsp;</em><code>answer</code><em>&nbsp;of size&nbsp;</em><code>n</code><em>, where&nbsp;</em><code>answer[i]</code><em>&nbsp;is the&nbsp;<strong>number</strong>&nbsp;of flowers that are in full bloom when the&nbsp;</em><code>i<sup>th</sup></code><em>&nbsp;person arrives.</em></p>



<p><strong>Example 1:</strong></p>



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2022/03/02/ex1new.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> flowers = [[1,6],[3,7],[9,12],[4,13]], persons = [2,3,7,11]
<strong>Output:</strong> [1,2,2,2]
<strong>Explanation: </strong>The figure above shows the times when the flowers are in full bloom and when the people arrive.
For each person, we return the number of flowers in full bloom during their arrival.
</pre>



<p><strong>Example 2:</strong></p>



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2022/03/02/ex2new.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> flowers = [[1,10],[3,3]], persons = [3,3,2]
<strong>Output:</strong> [2,2,1]
<strong>Explanation:</strong> The figure above shows the times when the flowers are in full bloom and when the people arrive.
For each person, we return the number of flowers in full bloom during their arrival.
</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>1 &lt;= flowers.length &lt;= 5 * 10<sup>4</sup></code></li><li><code>flowers[i].length == 2</code></li><li><code>1 &lt;= start<sub>i</sub>&nbsp;&lt;= end<sub>i</sub>&nbsp;&lt;= 10<sup>9</sup></code></li><li><code>1 &lt;= persons.length &lt;= 5 * 10<sup>4</sup></code></li><li><code>1 &lt;= persons[i] &lt;= 10<sup>9</sup></code></li></ul>



<h2><strong>Solution: Prefix Sum + Binary Search</strong></h2>



<p>Use a treemap to store the counts (ordered by time t), when a flower begins to bloom at start, we increase m[start], when it dies at end, we decrease m[end+1]. prefix_sum[t] indicates the # of blooming flowers at time t.</p>



<p>For each people, use binary search to find the latest # of flowers before his arrival.</p>



<p>Time complexity: O(nlogn + mlogn)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  vector&lt;int&gt; fullBloomFlowers(vector&lt;vector&lt;int&gt;&gt;&amp; flowers, vector&lt;int&gt;&amp; persons) {
    map&lt;int, int&gt; m{{0, 0}};
    for (const auto&amp; f : flowers)
      ++m[f[0]], --m[f[1] + 1];    
    int sum = 0;
    for (auto&amp; [t, c] : m)
      c = sum += c;    
    vector&lt;int&gt; ans;    
    for (int t : persons)      
      ans.push_back(prev(m.upper_bound(t))-&gt;second);
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/">花花酱 LeetCode 2251. Number of Flowers in Full Bloom</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1871. Jump Game VII</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1871-jump-game-vii/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1871-jump-game-vii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 06 Aug 2021 05:26:45 +0000</pubDate>
				<category><![CDATA[Binary Search]]></category>
		<category><![CDATA[binary search]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[sweep line]]></category>
		<category><![CDATA[two pointers]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=8487</guid>

					<description><![CDATA[<p>You are given a&#160;0-indexed&#160;binary string&#160;s&#160;and two integers&#160;minJump&#160;and&#160;maxJump. In the beginning, you are standing at index&#160;0, which is equal to&#160;'0'. You can move from index&#160;i&#160;to index&#160;j&#160;if&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1871-jump-game-vii/">花花酱 LeetCode 1871. Jump Game VII</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;binary string&nbsp;<code>s</code>&nbsp;and two integers&nbsp;<code>minJump</code>&nbsp;and&nbsp;<code>maxJump</code>. In the beginning, you are standing at index&nbsp;<code>0</code>, which is equal to&nbsp;<code>'0'</code>. You can move from index&nbsp;<code>i</code>&nbsp;to index&nbsp;<code>j</code>&nbsp;if the following conditions are fulfilled:</p>



<ul><li><code>i + minJump &lt;= j &lt;= min(i + maxJump, s.length - 1)</code>, and</li><li><code>s[j] == '0'</code>.</li></ul>



<p>Return&nbsp;<code>true</code><em>&nbsp;if you can reach index&nbsp;</em><code>s.length - 1</code><em>&nbsp;in&nbsp;</em><code>s</code><em>, or&nbsp;</em><code>false</code><em>&nbsp;otherwise.</em></p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "011010", minJump = 2, maxJump = 3
<strong>Output:</strong> true
<strong>Explanation:</strong>
In the first step, move from index 0 to index 3. 
In the second step, move from index 3 to index 5.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "01101110", minJump = 2, maxJump = 3
<strong>Output:</strong> false
</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>2 &lt;= s.length &lt;= 10<sup>5</sup></code></li><li><code>s[i]</code>&nbsp;is either&nbsp;<code>'0'</code>&nbsp;or&nbsp;<code>'1'</code>.</li><li><code>s[0] == '0'</code></li><li><code>1 &lt;= minJump &lt;= maxJump &lt; s.length</code></li></ul>



<h2><strong>Solution 1: TreeSet /Dequq + Binary Search</strong></h2>



<p>Maintain a set of reachable indices so far, for each &#8216;0&#8217; index check whether it can be reached from any of the elements in the set.</p>



<p>Time complexity: O(nlogn)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++/set</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 296 ms, 59.7MB
class Solution {
public:
  bool canReach(string s, int minJump, int maxJump) {
    if (s.back() != '0') return false;
    const int n = s.length();    
    set&lt;int&gt; seen{0};
    for (int i = minJump; i &lt; n; ++i) {
      if (s[i] != '0') continue;
      while (!seen.empty() &amp;&amp; (*seen.begin()) + maxJump &lt; i)
        seen.erase(seen.begin());
      auto it = seen.upper_bound(i - minJump);
      if (it != seen.begin() &amp;&amp; *prev(it) + minJump &lt;= i)        
        seen.insert(i);
    }
    return seen.count(n - 1);
  }
};</pre>

</div><h2 class="tabtitle">C++/deque</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 280 ms, 19MB
class Solution {
public:
  bool canReach(string s, int minJump, int maxJump) {
    if (s.back() != '0') return false;
    const int n = s.length();    
    deque&lt;int&gt; seen{0};
    for (int i = minJump; i &lt; n; ++i) {
      if (s[i] != '0') continue;
      while (!seen.empty() &amp;&amp; (seen.front()) + maxJump &lt; i)
        seen.pop_front();
      auto it = upper_bound(begin(seen), end(seen), i - minJump);
      if (it != seen.begin() &amp;&amp; *prev(it) + minJump &lt;= i)
        seen.push_back(i);
    }
    return seen.back() == n - 1;
  }
};</pre>
</div></div>



<h2><strong>Solution 2: Queue</strong></h2>



<p>Same idea, we can replace the deque in sol1 with a queue, and only check the smallest element in the queue.</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++/set</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 56ms, 19.2MB
class Solution {
public:
  bool canReach(string s, int minJump, int maxJump) {
    if (s.back() != '0') return false;
    const int n = s.length();    
    queue&lt;int&gt; q{{0}};
    for (int i = minJump; i &lt; n; ++i) {
      if (s[i] != '0') continue;
      while (!q.empty() &amp;&amp; q.front() + maxJump &lt; i)
        q.pop();
      if (!q.empty() &amp;&amp; q.front() + minJump &lt;= i)
        q.push(i);
    }
    return q.back() == n - 1;
  }
};</pre>
</div></div>



<p>Time complexity: O(n)<br>Space complexity: O(n)</p>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1871-jump-game-vii/">花花酱 LeetCode 1871. Jump Game VII</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1871-jump-game-vii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1589. Maximum Sum Obtained of Any Permutation</title>
		<link>https://zxi.mytechroad.com/blog/greedy/leetcode-1589-maximum-sum-obtained-of-any-permutation/</link>
					<comments>https://zxi.mytechroad.com/blog/greedy/leetcode-1589-maximum-sum-obtained-of-any-permutation/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 20 Sep 2020 06:11:13 +0000</pubDate>
				<category><![CDATA[Greedy]]></category>
		<category><![CDATA[greedy]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[sweep line]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7388</guid>

					<description><![CDATA[<p>We have an array of integers,&#160;nums, and an array of&#160;requests&#160;where&#160;requests[i] = [starti, endi]. The&#160;ith&#160;request asks for the sum of&#160;nums[starti] + nums[starti&#160;+ 1] + ... +&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/greedy/leetcode-1589-maximum-sum-obtained-of-any-permutation/">花花酱 LeetCode 1589. Maximum Sum Obtained of Any Permutation</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>We have an array of integers,&nbsp;<code>nums</code>, and an array of&nbsp;<code>requests</code>&nbsp;where&nbsp;<code>requests[i] = [start<sub>i</sub>, end<sub>i</sub>]</code>. The&nbsp;<code>i<sup>th</sup></code>&nbsp;request asks for the sum of&nbsp;<code>nums[start<sub>i</sub>] + nums[start<sub>i</sub>&nbsp;+ 1] + ... + nums[end<sub>i</sub>&nbsp;- 1] + nums[end<sub>i</sub>]</code>. Both&nbsp;<code>start<sub>i</sub></code>&nbsp;and&nbsp;<code>end<sub>i</sub></code>&nbsp;are&nbsp;<em>0-indexed</em>.</p>



<p>Return&nbsp;<em>the maximum total sum of all requests&nbsp;<strong>among all permutations</strong>&nbsp;of</em>&nbsp;<code>nums</code>.</p>



<p>Since the answer may be too large, return it&nbsp;<strong>modulo</strong>&nbsp;<code>10<sup>9</sup>&nbsp;+ 7</code>.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,3,4,5], requests = [[1,3],[0,1]]
<strong>Output:</strong> 19
<strong>Explanation:</strong> One permutation of nums is [2,1,3,4,5] with the following result: 
requests[0] -&gt; nums[1] + nums[2] + nums[3] = 1 + 3 + 4 = 8
requests[1] -&gt; nums[0] + nums[1] = 2 + 1 = 3
Total sum: 8 + 3 = 11.
A permutation with a higher total sum is [3,5,4,2,1] with the following result:
requests[0] -&gt; nums[1] + nums[2] + nums[3] = 5 + 4 + 2 = 11
requests[1] -&gt; nums[0] + nums[1] = 3 + 5  = 8
Total sum: 11 + 8 = 19, which is the best that you can do.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,3,4,5,6], requests = [[0,1]]
<strong>Output:</strong> 11
<strong>Explanation:</strong> A permutation with the max total sum is [6,5,4,3,2,1] with request sums [11].</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,3,4,5,10], requests = [[0,2],[1,3],[1,1]]
<strong>Output:</strong> 47
<strong>Explanation:</strong> A permutation with the max total sum is [4,10,5,3,2,1] with request sums [19,18,10].</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>n == nums.length</code></li><li><code>1 &lt;= n &lt;= 10<sup>5</sup></code></li><li><code>0 &lt;= nums[i]&nbsp;&lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= requests.length &lt;=&nbsp;10<sup>5</sup></code></li><li><code>requests[i].length == 2</code></li><li><code>0 &lt;= start<sub>i</sub>&nbsp;&lt;= end<sub>i</sub>&nbsp;&lt;&nbsp;n</code></li></ul>



<h2><strong>Solution: Greedy + Sweep line</strong></h2>



<p>Sort the numbers, and sort the frequency of each index, it&#8217;s easy to show largest number with largest frequency gives us max sum.</p>



<p>ans = sum(nums[i] * freq[i])</p>



<p>We can use sweep line to compute the frequency of each index in O(n) time and space.</p>



<p>For each request [start, end] : ++freq[start], &#8211;freq[end + 1]</p>



<p>Then the prefix sum of freq array is the frequency for each index.</p>



<p>Time complexity: O(nlogn)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">class Solution {
public:
  int maxSumRangeQuery(vector&lt;int&gt;&amp; nums, vector&lt;vector&lt;int&gt;&gt;&amp; requests) {
    constexpr int kMod = 1e9 + 7;
    const int n = nums.size();    
    vector&lt;long&gt; freq(n);
    for (const auto&amp; r : requests) {
      ++freq[r[0]];
      if (r[1] + 1 &lt; n) --freq[r[1] + 1];
    }
    for (int i = 1; i &lt; n; ++i)
      freq[i] += freq[i - 1];
    
    sort(begin(freq), end(freq));
    sort(begin(nums), end(nums));
    
    long ans = 0;
    for (int i = 0; i &lt; n; ++i)
      ans += freq[i] * nums[i];
    
    return ans % kMod;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/greedy/leetcode-1589-maximum-sum-obtained-of-any-permutation/">花花酱 LeetCode 1589. Maximum Sum Obtained of Any Permutation</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/greedy/leetcode-1589-maximum-sum-obtained-of-any-permutation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 452. Minimum Number of Arrows to Burst Balloons</title>
		<link>https://zxi.mytechroad.com/blog/geometry/leetcode-452-minimum-number-of-arrows-to-burst-balloons/</link>
					<comments>https://zxi.mytechroad.com/blog/geometry/leetcode-452-minimum-number-of-arrows-to-burst-balloons/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 23 Jun 2018 14:56:20 +0000</pubDate>
				<category><![CDATA[Geometry]]></category>
		<category><![CDATA[Greedy]]></category>
		<category><![CDATA[geometry]]></category>
		<category><![CDATA[greedy]]></category>
		<category><![CDATA[sweep line]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2926</guid>

					<description><![CDATA[<p>Problem There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-452-minimum-number-of-arrows-to-burst-balloons/">花花酱 LeetCode 452. Minimum Number of Arrows to Burst Balloons</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/DguJN47_mSg?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it&#8217;s horizontal, y-coordinates don&#8217;t matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 10<sup>4</sup> balloons.</p>
<p>An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with x<sub>start</sub> and x<sub>end</sub>bursts by an arrow shot at x if x<sub>start</sub> ≤ x ≤ x<sub>end</sub>. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.</p>
<p><b>Example:</b></p>
<pre class="crayon:false "><b>Input:</b>
[[10,16], [2,8], [1,6], [7,12]]

<b>Output:</b>
2

<b>Explanation:</b>
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).
</pre>
<h1><strong>Solution: Sweep Line</strong></h1>
<p>Time complexity: O(nlogn)</p>
<p>Space complexity: O(1)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 82 ms
class Solution {
public:
  int findMinArrowShots(vector&lt;pair&lt;int, int&gt;&gt;&amp; points) {
    if (points.empty()) return 0;
    sort(points.begin(), points.end(), 
         [&amp;](const pair&lt;int,int&gt;&amp; a, const pair&lt;int,int&gt;&amp; b){
           return a.second &lt; b.second;
         });
    int right = points.front().second;
    int ans = 1;
    for (const auto&amp; point : points) {
      if (point.first &gt; right) {
        right = point.second;
        ++ans;
      }
    }
    return ans;
  }
};</pre><p></p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/">花花酱 LeetCode 56. Merge Intervals</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-57-insert-interval/">花花酱 LeetCode 57. Insert Interval</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-759-employee-free-time/">花花酱 LeetCode 759. Employee Free Time</a></li>
<li><a href="http://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-729-my-calendar-i/">花花酱 LeetCode 729. My Calendar I</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-731-my-calendar-ii/">花花酱 LeetCode 731. My Calendar II &amp;#8211; 花花酱</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/732-my-calendar-iii/">花花酱 LeetCode 732. My Calendar III</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-452-minimum-number-of-arrows-to-burst-balloons/">花花酱 LeetCode 452. Minimum Number of Arrows to Burst Balloons</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/geometry/leetcode-452-minimum-number-of-arrows-to-burst-balloons/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 759. Employee Free Time</title>
		<link>https://zxi.mytechroad.com/blog/geometry/leetcode-759-employee-free-time/</link>
					<comments>https://zxi.mytechroad.com/blog/geometry/leetcode-759-employee-free-time/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 09 Jan 2018 02:11:26 +0000</pubDate>
				<category><![CDATA[Geometry]]></category>
		<category><![CDATA[Hard]]></category>
		<category><![CDATA[intersection]]></category>
		<category><![CDATA[interval]]></category>
		<category><![CDATA[sorting]]></category>
		<category><![CDATA[sweep line]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1574</guid>

					<description><![CDATA[<p>题目大意：给你每个员工的日历，让你找出所有员工都有空的时间段。 Problem: We are given a list schedule of employees, which represents the working time for each employee. Each employee has a list of non-overlapping Intervals, and these&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-759-employee-free-time/">花花酱 LeetCode 759. Employee Free Time</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/VTgF52uGK0Y?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p>题目大意：给你每个员工的日历，让你找出所有员工都有空的时间段。</p>
<p><strong>Problem:</strong></p>
<p>We are given a list <code>schedule</code> of employees, which represents the working time for each employee.</p>
<p>Each employee has a list of non-overlapping <code>Intervals</code>, and these intervals are in sorted order.</p>
<p>Return the list of finite intervals representing <b>common, positive-length free time</b> for <i>all</i> employees, also in sorted order.</p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]]
Output: [[3,4]]
Explanation:
There are a total of three employees, and all common
free time intervals would be [-inf, 1], [3, 4], [10, inf].
We discard any intervals that contain inf as they aren't finite.</pre><p><b>Example 2:</b></p><pre class="crayon-plain-tag">Input: schedule = [[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]]
Output: [[5,6],[7,9]]</pre><p>(Even though we are representing <code>Intervals</code> in the form <code>[x, y]</code>, the objects inside are <code>Intervals</code>, not lists or arrays. For example, <code>schedule[0][0].start = 1, schedule[0][0].end = 2</code>, and <code>schedule[0][0][0]</code> is not defined.)</p>
<p>Also, we wouldn&#8217;t include intervals like [5, 5] in our answer, as they have zero length.</p>
<p><b>Note:</b></p>
<ol>
<li><code>schedule</code> and <code>schedule[i]</code> are lists with lengths in range <code>[1, 50]</code>.</li>
<li><code>0 &lt;= schedule[i].start &lt; schedule[i].end &lt;= 10^8</code>.</li>
</ol>
<p><ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"><br />
</ins></p>
<p><strong>Idea:</strong></p>
<p>Merge Intervals (virtually)</p>
<p><img class="alignnone wp-image-1580 size-full" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/759-ep154.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/759-ep154.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/759-ep154-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/759-ep154-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><strong>Solution:</strong></p>
<p>C++</p>
<p>Time complexity: O(nlogn)</p>
<p>Space complexity: O(n)</p>
<p>n is the total number of intervals, n &lt;= 2500</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 81 ms
class Solution {
public:
    vector&lt;Interval&gt; employeeFreeTime(vector&lt;vector&lt;Interval&gt;&gt;&amp; schedule) {
      vector&lt;Interval&gt; all;
      for (const auto intervals : schedule)
        all.insert(all.end(), intervals.begin(), intervals.end());
      std::sort(all.begin(), all.end(), 
                [](const Interval&amp; a, const Interval&amp; b){
                  return a.start &lt; b.start;
                });
      vector&lt;Interval&gt; ans;
      int end = all.front().end;
      for (const Interval&amp; busy : all) {
        if (busy.start &gt; end) 
          ans.emplace_back(end, busy.start);  
        end = max(end, busy.end);
      }
      return ans;
    }
};</pre><p><strong>Related Problems:</strong></p>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/">[解题报告] LeetCode 56. Merge Intervals</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-57-insert-interval/">[解题报告] LeetCode 57. Insert Interval</a></li>
<li><a href="http://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-729-my-calendar-i/">[解题报告] LeetCode 729. My Calendar &#8211; 花花酱</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-731-my-calendar-ii/">[解题报告] LeetCode 731. My Calendar II &#8211; 花花酱</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/732-my-calendar-iii/">花花酱 LeetCode 732. My Calendar III</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-759-employee-free-time/">花花酱 LeetCode 759. Employee Free Time</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/geometry/leetcode-759-employee-free-time/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 731. My Calendar II &#8211; 花花酱</title>
		<link>https://zxi.mytechroad.com/blog/geometry/leetcode-731-my-calendar-ii/</link>
					<comments>https://zxi.mytechroad.com/blog/geometry/leetcode-731-my-calendar-ii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 20 Nov 2017 02:24:40 +0000</pubDate>
				<category><![CDATA[Easy]]></category>
		<category><![CDATA[Geometry]]></category>
		<category><![CDATA[overlap]]></category>
		<category><![CDATA[range]]></category>
		<category><![CDATA[sweep line]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=864</guid>

					<description><![CDATA[<p>Problem:  Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event will not cause a triple booking. Your class will have&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-731-my-calendar-ii/">花花酱 LeetCode 731. My Calendar II &#8211; 花花酱</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/rRMdxFA-8G4?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p><strong>Problem: </strong></p>
<p>Implement a <code>MyCalendarTwo</code> class to store your events. A new event can be added if adding the event will not cause a <b>triple</b> booking.</p>
<p>Your class will have one method, <code>book(int start, int end)</code>. Formally, this represents a booking on the half open interval <code>[start, end)</code>, the range of real numbers <code>x</code> such that <code>start &lt;= x &lt; end</code>.</p>
<p>A <i>triple booking</i> happens when <b>three</b> events have some non-empty intersection (ie., there is some time that is common to all 3 events.)</p>
<p>For each call to the method <code>MyCalendar.book</code>, return <code>true</code> if the event can be added to the calendar successfully without causing a <b>triple</b> booking. Otherwise, return <code>false</code> and do not add the event to the calendar.</p>
<p>Your class will be called like this: <code>MyCalendar cal = new MyCalendar();</code> <code>MyCalendar.book(start, end)</code></p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">MyCalendar();
MyCalendar.book(10, 20); // returns true
MyCalendar.book(50, 60); // returns true
MyCalendar.book(10, 40); // returns true
MyCalendar.book(5, 15); // returns false
MyCalendar.book(5, 10); // returns true
MyCalendar.book(25, 55); // returns true
Explanation&lt;b&gt;:&lt;/b&gt; 
The first two events can be booked.  The third event can be double booked.
The fourth event (5, 15) can't be booked, because it would result in a triple booking.
The fifth event (5, 10) can be booked, as it does not use time 10 which is already double booked.
The sixth event (25, 55) can be booked, as the time in [25, 40) will be double booked with the third event;
the time [40, 50) will be single booked, and the time [50, 55) will be double booked with the second event.</pre><p><b>Note:</b></p>
<p>&nbsp;</p>
<ul>
<li>The number of calls to <code>MyCalendar.book</code> per test case will be at most <code>1000</code>.</li>
<li>In calls to <code>MyCalendar.book(start, end)</code>, <code>start</code> and <code>end</code> are integers in the range <code>[0, 10^9]</code>.</li>
</ul>
<p><strong>Idea:</strong></p>
<p>Brute Force</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/731-ep113-1.png"><img class="alignnone size-full wp-image-875" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/731-ep113-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/731-ep113-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/731-ep113-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/731-ep113-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/731-ep113-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><b style="font-size: 1rem;">Solution1:</b></p>
<p>Brute Force</p>
<p>Time Complexity: O(n^2)</p>
<p>Space Complexity: O(n)</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 82 ms
class MyCalendarTwo {
public:
    MyCalendarTwo() {}
    
    bool book(int start, int end) {
        for (const auto&amp; kv : overlaps_)
            if (max(start, kv.first) &lt; min(end, kv.second)) return false;
        
        for (const auto&amp; kv : booked_) {
            const int ss = max(start, kv.first);
            const int ee = min(end, kv.second);
            if (ss &lt; ee) overlaps_.emplace_back(ss, ee);
        }
        
        booked_.emplace_back(start, end);
        return true;
    }
private:
    vector&lt;pair&lt;int, int&gt;&gt; booked_;
    vector&lt;pair&lt;int, int&gt;&gt; overlaps_;
};</pre><p>&nbsp;</p>
<p>Java</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 156 ms
class MyCalendarTwo {
    
    private List&lt;int[]&gt; booked_;
    private List&lt;int[]&gt; overlaps_;

    public MyCalendarTwo() {
        booked_ = new ArrayList&lt;&gt;();
        overlaps_ = new ArrayList&lt;&gt;();
    }
    
    public boolean book(int start, int end) {
        for (int[] range : overlaps_)
            if (Math.max(range[0], start) &lt; Math.min(range[1], end)) 
                return false;
        
        for (int[] range : booked_) {
            int ss = Math.max(range[0], start);
            int ee = Math.min(range[1], end);
            if (ss &lt; ee) overlaps_.add(new int[]{ss, ee});
        }
        
        booked_.add(new int[]{start, end});
        return true;
    }

}</pre><p>Python</p><pre class="crayon-plain-tag">"""
Author: Huahua
Runtime: 638 ms
"""
class MyCalendarTwo:

    def __init__(self):
        self.booked_ = []
        self.overlaps_ = []

    def book(self, start, end):
        for s, e in self.overlaps_:
            if start &lt; e and end &gt; s: return False
        
        for s, e in self.booked_:            
            if start &lt; e and end &gt; s: 
                self.overlaps_.append([max(start, s), min(end, e)])
        
        self.booked_.append([start, end])
        return True</pre><p>&nbsp;</p>
<p><strong>Solution 2:</strong></p>
<p>Counting</p>
<p>Time Complexity: O(n^2logn)</p>
<p>Space Complexity: O(n)</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 212 ms
class MyCalendarTwo {
public:
    MyCalendarTwo() {}
    
    bool book(int start, int end) {
        ++delta_[start];
        --delta_[end];
        int count = 0;
        for (const auto&amp; kv : delta_) {
            count += kv.second;
            if (count == 3) {
                --delta_[start];
                ++delta_[end];
                return false;
            }
            if (kv.first &gt; end) break;
        }
        return true;
    }
private:
    map&lt;int, int&gt; delta_;
};</pre><p>&nbsp;</p>
<p><strong>Related Problems:</strong></p>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/binary-search/leetcode-729-my-calendar-i/">[解题报告] LeetCode 729. My Calendar I</a></li>
<li><a href="http://zxi.mytechroad.com/blog/data-structure/leetcode-715-range-module/">[解题报告] LeetCode 715. Range Module</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-57-insert-interval/">[解题报告] LeetCode 57. Insert Interval</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/">[解题报告] LeetCode 56. Merge Intervals</a></li>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-699-falling-squares/">[解题报告] LeetCode 699. Falling Squares</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-731-my-calendar-ii/">花花酱 LeetCode 731. My Calendar II &#8211; 花花酱</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/geometry/leetcode-731-my-calendar-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 56. Merge Intervals</title>
		<link>https://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/</link>
					<comments>https://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 15 Oct 2017 03:13:20 +0000</pubDate>
				<category><![CDATA[Geometry]]></category>
		<category><![CDATA[interval]]></category>
		<category><![CDATA[merge]]></category>
		<category><![CDATA[sort]]></category>
		<category><![CDATA[sweep line]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=578</guid>

					<description><![CDATA[<p>Problem: Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18]. Idea: Sweep line Solution: C++ [crayon-663cb36684da1013990112/] Python [crayon-663cb36684da4903046579/] &#160; Related Problems:&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/">花花酱 LeetCode 56. Merge Intervals</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/6tLHjei-f0I?feature=oembed" frameborder="0" gesture="media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>Given a collection of intervals, merge all overlapping intervals.</p>
<p>For example,<br />
Given <code>[1,3],[2,6],[8,10],[15,18]</code>,<br />
return <code>[1,6],[8,10],[15,18]</code>.</p>
<p><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
<p><strong>Idea:</strong></p>
<p>Sweep line</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/56-ep85-1.png"><img class="alignnone size-full wp-image-584" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/56-ep85-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/56-ep85-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/56-ep85-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/56-ep85-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/10/56-ep85-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><strong>Solution: </strong></p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 12 ms
class Solution {
public:
    vector&lt;Interval&gt; merge(vector&lt;Interval&gt;&amp; intervals) {
        if (intervals.empty()) return {};
        
        std::sort(intervals.begin(), intervals.end(), 
                  [](const Interval&amp; a, const Interval&amp; b){
                        return a.start &lt; b.start;
                    });
        
        vector&lt;Interval&gt; ans;        
        for (const auto&amp; interval : intervals) {
            if (ans.empty() || interval.start &gt; ans.back().end) {
                ans.push_back(interval);
            } else {
                ans.back().end = max(ans.back().end, interval.end);
            }
        }
        
        return ans;
    }
};</pre><p>Python</p><pre class="crayon-plain-tag">"""
Author: Huahua
Runtime: 69 ms
"""
class Solution(object):
    def merge(self, intervals):
        ans = []
        for interval in sorted(intervals, key=lambda x: x.start):
            if not ans or interval.start &gt; ans[-1].end:
                ans.append(interval)
            else:
                ans[-1].end = max(ans[-1].end, interval.end)
        return ans</pre><p>&nbsp;</p>
<p><strong>Related Problems:</strong></p>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/geometry/leetcode-57-insert-interval/">[解题报告] LeetCode 57. Insert Interval</a></li>
<li><a href="http://zxi.mytechroad.com/blog/tree/leetcode-218-the-skyline-problem/">[解题报告] LeetCode 218. The Skyline Problem</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/">花花酱 LeetCode 56. Merge Intervals</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/geometry/leetcode-56-merge-intervals/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 218. The Skyline Problem</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-218-the-skyline-problem/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-218-the-skyline-problem/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 23 Sep 2017 03:08:33 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[Tree]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[heap]]></category>
		<category><![CDATA[skyline]]></category>
		<category><![CDATA[sweep line]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=387</guid>

					<description><![CDATA[<p>Problem: A city&#8217;s skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-218-the-skyline-problem/">花花酱 LeetCode 218. The Skyline Problem</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/8Kd-Tn_Rz7s?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>A city&#8217;s skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are <b>given the locations and height of all the buildings</b> as shown on a cityscape photo (Figure A), write a program to <b>output the skyline</b> formed by these buildings collectively (Figure B).</p>
<p><a href="https://leetcode.com/static/images/problemset/skyline1.jpg" target="_blank" rel="noopener"><img src="https://leetcode.com/static/images/problemset/skyline1.jpg" alt="Buildings" border="0" /> </a><a href="https://leetcode.com/static/images/problemset/skyline2.jpg" target="_blank" rel="noopener"><img src="https://leetcode.com/static/images/problemset/skyline2.jpg" alt="Skyline Contour" border="0" /></a></p>
<p>The geometric information of each building is represented by a triplet of integers <code>[Li, Ri, Hi]</code>, where <code>Li</code> and <code>Ri</code> are the x coordinates of the left and right edge of the ith building, respectively, and <code>Hi</code> is its height. It is guaranteed that <code>0 ≤ Li, Ri ≤ INT_MAX</code>, <code>0 &lt; Hi ≤ INT_MAX</code>, and <code>Ri - Li &gt; 0</code>. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.</p>
<p>For instance, the dimensions of all buildings in Figure A are recorded as: <code>[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] </code>.</p>
<p>The output is a list of &#8220;<b>key points</b>&#8221; (red dots in Figure B) in the format of <code>[ [x1,y1], [x2, y2], [x3, y3], ... ]</code> that uniquely defines a skyline. <b>A key point is the left endpoint of a horizontal line segment</b>. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.</p>
<p>For instance, the skyline in Figure B should be represented as:<code>[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]</code>.</p>
<p><b>Notes:</b></p>
<ul>
<li>The number of buildings in any input list is guaranteed to be in the range <code>[0, 10000]</code>.</li>
<li>The input list is already sorted in ascending order by the left x position <code>Li</code>.</li>
<li>The output list must be sorted by the x position.</li>
<li>There must be no consecutive horizontal lines of equal height in the output skyline. For instance, <code>[...[2 3], [4 5], [7 5], [11 5], [12 7]...]</code> is not acceptable; the three lines of height 5 should be merged into one in the final output as such: <code>[...[2 3], [4 5], [12 7], ...]</code></li>
</ul>
<p><ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"> </ins></p>
<p><strong>Idea:</strong></p>
<p>Sweep line</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-1.png"><img class="alignnone size-full wp-image-393" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-2.png"><img class="alignnone size-full wp-image-392" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-2-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-2-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><img class="alignnone size-full wp-image-391" style="font-size: 1rem;" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-3-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-3-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-390" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-4-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/218-ep68-4-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
<p><strong>Time Complexity: </strong></p>
<p>O(nlogn)</p>
<p><strong>Space Complexity:</strong></p>
<p>O(n)</p>
<h1><strong>Solution1: Heap </strong></h1>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">class Solution {
public:
    vector&lt;pair&lt;int, int&gt;&gt; getSkyline(vector&lt;vector&lt;int&gt;&gt;&amp; buildings) {
        // events,   x,   h,   id,  type (1=entering, -1=leaving)
        vector&lt;Event&gt; events;
        
        int id = 0;
        for (const auto&amp; b : buildings) {
            events.push_back(Event{id, b[0], b[2], 1});
            events.push_back(Event{id, b[1], b[2], -1});
            ++id;
        }
        
        // Sort events by x
        sort(events.begin(), events.end());
        
        // Init the heap
        MaxHeap heap(buildings.size());
        
        vector&lt;pair&lt;int, int&gt;&gt; ans;
        // Process all the events
        for (const auto&amp; event: events) {            
            int x = event.x;
            int h = event.h;
            int id = event.id;
            int type = event.type;            
            
            if (type == 1) {
                if (h &gt; heap.Max()) 
                    ans.emplace_back(x, h);
                heap.Add(h, id);
            } else {
                heap.Remove(id);
                if (h &gt; heap.Max())
                    ans.emplace_back(x, heap.Max());
            }            
        }
        
        return ans;
    }
private:
    struct Event {
        int id;
        int x;       
        int h;
        int type;
        
        // sort by x+, type-, h, 
        bool operator&lt;(const Event&amp; e) const {
            if (x == e.x)                
                // Entering event h from large to small
                // Leaving event h from small to large
                return type * h &gt; e.type * e.h;
            
            return x &lt; e.x;
        }
    };
    
    class MaxHeap {
    public:
        MaxHeap(int max_items): 
            idx_(max_items, -1), vals_(max_items), size_(0) {}
        
        // Add an item into the heap. O(log(n))
        void Add(int key, int id) {
            idx_[id] = size_;
            vals_[size_] = {key, id};
            ++size_;
            HeapifyUp(idx_[id]);
        }
        
        // Remove an item. O(log(n))
        void Remove(int id) {
            int idx_to_evict = idx_[id];
            // swap with the last element
            SwapNode(idx_to_evict, size_ - 1);
            --size_;
            HeapifyDown(idx_to_evict);
            HeapifyDown(idx_to_evict);
        }
        
        bool Empty() const {
            return size_ == 0;
        }
        
        // Return the max of heap
        int Max() const {
            return Empty() ? 0 : vals_.front().first;
        }
    private:
        void SwapNode(int i, int j) {
            if (i == j) return;
            std::swap(idx_[vals_[i].second], idx_[vals_[j].second]);
            std::swap(vals_[i], vals_[j]);
        }
        
        void HeapifyUp(int i) {
            while (i != 0)  {            
                int p = (i - 1) / 2;
                if (vals_[i].first &lt;= vals_[p].first) 
                    return;

                SwapNode(i, p);                
                i = p;
            }
        }
        
        // Make the heap valid again. O(log(n))
        void HeapifyDown(int i) {
            while (true) {
                int c1 = i*2 + 1;
                int c2 = i*2 + 2;

                // No child
                if (c1 &gt;= size_) return;

                // Get the index of the max child
                int c = (c2 &lt; size_ 
                      &amp;&amp; vals_[c2].first &gt; vals_[c1].first ) ? c2 : c1;

                // If key[c] is greater than key[i], swap them and
                // continue to HeapifyDown(c)
                if (vals_[c].first &lt;= vals_[i].first) 
                    return;
                
                SwapNode(c, i);
                i = c;
            }
        }
        
        // {key, id}
        vector&lt;pair&lt;int,int&gt;&gt; vals_;
        
        // Index of the i-th item in vals_ 
        vector&lt;int&gt; idx_;
        
        int size_;
    };
};</pre><p></div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 91 ms (beats 79.1%)
class Solution {
    private MaxHeap heap;
    
    public List&lt;int[]&gt; getSkyline(int[][] buildings) {
        int n = buildings.length;        
        // {x, h, id}
        ArrayList&lt;int[]&gt; es = new ArrayList&lt;int[]&gt;();
        
        for (int i = 0; i &lt; n; ++i) {
            es.add(new int[]{ buildings[i][0], buildings[i][2], i});
            es.add(new int[]{ buildings[i][1], -buildings[i][2], i});
        }
        
        es.sort((e1, e2) -&gt; {
            return e1[0] == e2[0] ? e2[1] - e1[1] : e1[0] - e2[0]; });
        
        
        List&lt;int[]&gt; ans = new ArrayList&lt;int[]&gt;();
        
        heap = new MaxHeap(n);
        
        for (int[] e : es) {
            int x = e[0];
            int h = e[1];
            int id = e[2];
            
            Boolean entering = h &gt; 0;
            h = Math.abs(h);
            
            if (entering) {
                if (h &gt; heap.max())
                    ans.add(new int[]{x, h});
                heap.add(h, id);
            } else {
                heap.remove(id);
                if (h &gt; heap.max())
                    ans.add(new int[]{x, heap.max()});
            }
        }
        
        return ans;
    }
    
    private class MaxHeap {
        // (key, id)
        private List&lt;int[]&gt; nodes;
        
        // idx[i] = index of building[i] in nodes
        private int[] idx;
        
        public MaxHeap(int size) {
            idx = new int[size];
            nodes = new ArrayList&lt;int[]&gt;();
        }
        
        public void add(int key, int id) {
            idx[id] = nodes.size();
            nodes.add(new int[]{key, id});
            heapifyUp(idx[id]);
        }
        
        public void remove(int id) {
            int idx_to_evict = idx[id];
            swapNode(idx_to_evict, nodes.size() - 1);
            idx[id] = -1;
            nodes.remove(nodes.size() - 1);
            heapifyUp(idx_to_evict);
            heapifyDown(idx_to_evict);
        }
        
        public Boolean empty() {
            return nodes.isEmpty();
        }
        
        public int max() {
            return empty() ? 0 : nodes.get(0)[0];
        }
        
        private void heapifyUp(int i) {            
            while (i != 0) {            
                int p = (i - 1) / 2;
                if (nodes.get(i)[0] &lt;= nodes.get(p)[0])
                    return;
                
                swapNode(i, p);
                i = p;
            }
        }
        
        private void swapNode(int i, int j) {
            int tmpIdx = idx[nodes.get(i)[1]];
            idx[nodes.get(i)[1]] = idx[nodes.get(j)[1]];
            idx[nodes.get(j)[1]] = tmpIdx;

            int[] tmpNode = nodes.get(i);
            nodes.set(i, nodes.get(j));
            nodes.set(j, tmpNode);
        }
        
        private void heapifyDown(int i) {
            while (true) {
                int c1 = i*2 + 1;
                int c2 = i*2 + 2;

                if (c1 &gt;= nodes.size()) return;

                int c = (c2 &lt; nodes.size() 
                      &amp;&amp; nodes.get(c2)[0] &gt; nodes.get(c1)[0]) ? c2 : c1;
                
                if (nodes.get(c)[0] &lt;= nodes.get(i)[0])
                    return;
                
                swapNode(c, i);
                i = c;
            }
        }
        
    }
}</pre><p></div></div></p>
<h1>Solution 2: Multiset</h1>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Time Complexity: O(nlogn)
// Space Complexity: O(n)
// Running Time: 22 ms
class Solution {
public:
    vector&lt;pair&lt;int, int&gt;&gt; getSkyline(vector&lt;vector&lt;int&gt;&gt;&amp; buildings) {
        typedef pair&lt;int, int&gt; Event; 
        // events,  x,   h
        vector&lt;Event&gt; es;        
        hs_.clear();
        
        for (const auto&amp; b : buildings) {
            es.emplace_back(b[0], b[2]);
            es.emplace_back(b[1], -b[2]);
        }
        
        // Sort events by x
        sort(es.begin(), es.end(), [](const Event&amp; e1, const Event&amp; e2){
            if (e1.first == e2.first) return e1.second &gt; e2.second;
            return e1.first &lt; e2.first;
        });
        
        vector&lt;pair&lt;int, int&gt;&gt; ans;
        
        // Process all the events
        for (const auto&amp; e: es) {            
            int x = e.first;
            bool entering = e.second &gt; 0;
            int h = abs(e.second);
            
            if (entering) {                
                if (h &gt; this-&gt;maxHeight()) 
                    ans.emplace_back(x, h);
                hs_.insert(h);
            } else {
                hs_.erase(hs_.equal_range(h).first);
                if (h &gt; this-&gt;maxHeight())
                    ans.emplace_back(x, this-&gt;maxHeight());
            }            
        }
        
        return ans;
    }
private:
    int maxHeight() const {
        if (hs_.empty()) return 0;
        return *hs_.rbegin();
    }
    multiset&lt;int&gt; hs_;
};</pre><p></div></div></p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-218-the-skyline-problem/">花花酱 LeetCode 218. The Skyline Problem</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-218-the-skyline-problem/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
