-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
56b8213
commit 1abd7fe
Showing
2 changed files
with
110 additions
and
0 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
docs/_posts/2023-11-27-2147-Number-of-Ways-to-Divide-a-Long-Corridor.markdown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
--- | ||
layout: post | ||
title: "2147 Number of Ways to Divide a Long Corridor" | ||
date: 2023-11-26 11:52:03 -0600 | ||
categories: algorithms greedy | ||
--- | ||
|
||
Link to the problem: [LeetCode2147 Number of Ways to Divide a Long Corridor](https://leetcode.com/problems/number-of-ways-to-divide-a-long-corridor/) | ||
|
||
A very basic observation is that if there are no seats or odd number of seat in our Corridor, there could be no way to divide it, which means if the number of `'S'` in the input string `corridor` is 0 or odd, the return answer should be 0. | ||
|
||
If we tag the first seat we encounter as the first seat, which is an odd number, and the second seat tagged as even, we can found that the divider can be only placed between the even seat and the following odd seat. Further, the number of plants between these two consecutive seats, happen to be the number of possibilities that the divier can be put between these two seats. | ||
|
||
Say we got `S(1), S(2), S(3) ... S(2n - 1), S(2n)` at total `2n` number of `'S'` in the input string `corridor`. Since there have to be a divider after every 2 consecutive seats(expect the last two seats), we need to place `n - 1` divider in the long corridor. And from the conclusion above, the number of possible positions of placing a divider between `S(2)` and `S(3)` equal to the index of `S(3)` substract the index of `S(2)`, the number of possible positions of placing a divider between `S(4)` and `S(5)` equal to the index of `S(5)` substract the index of `S(4)` and so on. There are `n - 1` dividers to be placed, and the final number of posibilities equals to the product of the number of possibilities of each divider. | ||
|
||
In the language of math: | ||
P = P1 * P2 * ... * Pn-1 | ||
|
||
Since: | ||
P1 = indexOf(S(3)) - indexOf(S(2)) | ||
P2 = indexOf(S(5)) - indexOf(S(4)) | ||
... | ||
Pn-1 = indexOf(S(2n-1)) - indexOf(S(2n-2)) | ||
|
||
We get: | ||
P = (indexOf(S(3)) - indexOf(S(2))) * (indexOf(S(5)) - indexOf(S(4))) * ... * (indexOf(S(2n-1)) - indexOf(S(2n-2))) | ||
|
||
With this idea, we come up with the following solution: | ||
|
||
{% highlight java %} | ||
class Solution { | ||
int MOD = 1_000_000_007; | ||
public int numberOfWays(String corridor) { | ||
long ret = 1; | ||
List<Integer> list = new ArrayList<>(); | ||
for (int i = 0; i < corridor.length(); i++) { | ||
if (corridor.charAt(i) == 'S') { | ||
list.add(i); | ||
} | ||
} | ||
if (list.size() == 0 || list.size() % 2 != 0) return 0; | ||
for (int i = 1; i + 1 < list.size(); i += 2) { | ||
ret = (ret * (list.get(i + 1) - list.get(i))) % MOD; | ||
} | ||
|
||
return (int)ret; | ||
} | ||
} | ||
{% endhighlight %} | ||
|
||
Further, We can even spare the work of creating the list that we use to store the indices of `'S'`. Instead, we keep track of the lastIndex of the 'S' and the maintain a flag that shows the count of 'S' we encounter so far is odd or even while calculating the final product throught only one iteration of the input corridor string. In this way, we can optimize the space complexity to O(1). The algorithm is shown as follows: | ||
|
||
{% highlight java %} | ||
class Solution { | ||
int MOD = 1_000_000_007; | ||
public int numberOfWays(String corridor) { | ||
long ret = 1; | ||
boolean isEven = true; | ||
int lastIdx = -1; | ||
for (int i = 0; i < corridor.length(); i++) { | ||
if (corridor.charAt(i) == 'S') { | ||
isEven = !isEven; | ||
if (!isEven && lastIdx != -1) { | ||
ret = (ret * (i - lastIdx)) % MOD; | ||
} | ||
lastIdx = i; | ||
} | ||
} | ||
|
||
return (isEven && lastIdx != -1) ? (int)ret : 0; | ||
} | ||
} | ||
{% endhighlight %} | ||
|
||
|
||
|
34 changes: 34 additions & 0 deletions
34
src/algorithmns/Greedy/2147NumberOfWaysToDivideALongCorridor/Solution.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
class Solution { | ||
int MOD = 1_000_000_007; | ||
// public int numberOfWays(String corridor) { | ||
// long ret = 1; | ||
// List<Integer> list = new ArrayList<>(); | ||
// for (int i = 0; i < corridor.length(); i++) { | ||
// if (corridor.charAt(i) == 'S') { | ||
// list.add(i); | ||
// } | ||
// } | ||
// if (list.size() == 0 || list.size() % 2 != 0) return 0; | ||
// for (int i = 1; i + 1 < list.size(); i += 2) { | ||
// ret = (ret * (list.get(i + 1) - list.get(i))) % MOD; | ||
// } | ||
|
||
// return (int)ret; | ||
// } | ||
public int numberOfWays(String corridor) { | ||
long ret = 1; | ||
boolean isEven = true; | ||
int lastIdx = -1; | ||
for (int i = 0; i < corridor.length(); i++) { | ||
if (corridor.charAt(i) == 'S') { | ||
isEven = !isEven; | ||
if (!isEven && lastIdx != -1) { | ||
ret = (ret * (i - lastIdx)) % MOD; | ||
} | ||
lastIdx = i; | ||
} | ||
} | ||
|
||
return (isEven && lastIdx != -1) ? (int)ret : 0; | ||
} | ||
} |