Skip to content

Commit 6271a90

Browse files
committed
solve aylei#30
1 parent b68b135 commit 6271a90

File tree

4 files changed

+160
-27
lines changed

4 files changed

+160
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Run `cargo test test_{id}` to test the solution for "question #id".
66

77
Working in progress, to do:
88

9-
- [ ] auto generation of solution list
9+
- [ ] auto generation of solution list (when 100 problems solved)
1010

1111
## Usage
1212

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ mod n0026_remove_duplicates_from_sorted_array;
2929
mod n0027_remove_element;
3030
mod n0028_implement_strstr;
3131
mod n0029_divide_two_integers;
32+
mod n0030_substring_with_concatenation_of_all_words;

src/n0029_divide_two_integers.rs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
/**
22
* [29] Divide Two Integers
33
*
4-
* Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.
5-
*
6-
* Return the quotient after dividing dividend by divisor.
7-
*
8-
* The integer division should truncate toward zero.
9-
*
10-
* Example 1:
11-
*
12-
*
13-
* Input: dividend = 10, divisor = 3
14-
* Output: 3
15-
*
16-
* Example 2:
17-
*
18-
*
19-
* Input: dividend = 7, divisor = -3
20-
* Output: -2
21-
*
22-
* Note:
23-
*
24-
*
25-
* Both dividend and divisor will be 32-bit signed integers.
26-
* The divisor will never be 0.
27-
* Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [-2^31, 2^31 - 1]. For the purpose of this problem, assume that your function returns 2^31 - 1 when the division result overflows.
28-
*
4+
* Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.
5+
*
6+
* Return the quotient after dividing dividend by divisor.
7+
*
8+
* The integer division should truncate toward zero.
9+
*
10+
* Example 1:
11+
*
12+
*
13+
* Input: dividend = 10, divisor = 3
14+
* Output: 3
15+
*
16+
* Example 2:
17+
*
18+
*
19+
* Input: dividend = 7, divisor = -3
20+
* Output: -2
21+
*
22+
* Note:
23+
*
24+
*
25+
* Both dividend and divisor will be 32-bit signed integers.
26+
* The divisor will never be 0.
27+
* Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [-2^31, 2^31 - 1]. For the purpose of this problem, assume that your function returns 2^31 - 1 when the division result overflows.
28+
*
2929
*
3030
*/
3131
pub struct Solution {}
@@ -34,7 +34,7 @@ pub struct Solution {}
3434

3535
impl Solution {
3636
pub fn divide(dividend: i32, divisor: i32) -> i32 {
37-
37+
0
3838
}
3939
}
4040

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/**
2+
* [30] Substring with Concatenation of All Words
3+
*
4+
* You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
5+
*
6+
* Example 1:
7+
*
8+
*
9+
* Input:
10+
* s = "barfoothefoobarman",
11+
* words = ["foo","bar"]
12+
* Output: [0,9]
13+
* Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
14+
* The output order does not matter, returning [9,0] is fine too.
15+
*
16+
*
17+
* Example 2:
18+
*
19+
*
20+
* Input:
21+
* s = "wordgoodgoodgoodbestword",
22+
* words = ["word","good","best","word"]
23+
* Output: []
24+
*
25+
*
26+
*/
27+
pub struct Solution {}
28+
29+
// submission codes start here
30+
struct Term {
31+
expect: i32,
32+
count: i32,
33+
}
34+
impl Term {
35+
fn new(expect: i32, count: i32) -> Self {
36+
Term{expect, count}
37+
}
38+
fn inc_expect(&mut self) {
39+
self.expect += 1;
40+
}
41+
fn inc(&mut self) {
42+
self.count += 1;
43+
}
44+
fn dec(&mut self) {
45+
self.count -= 1;
46+
}
47+
fn exhausted(&self) -> bool {
48+
self.count > self.expect
49+
}
50+
fn reset(&mut self) {
51+
self.count = 0;
52+
}
53+
}
54+
55+
use std::collections::HashMap;
56+
use std::collections::hash_map::Entry;
57+
58+
impl Solution {
59+
pub fn find_substring(s: String, words: Vec<String>) -> Vec<i32> {
60+
if words.len() < 1 { return vec![] }
61+
let word_len = words[0].len();
62+
if word_len < 1 { return vec![] }
63+
let substr_len = word_len * words.len();
64+
let mut map: HashMap<&str, Term> = HashMap::with_capacity(words.len());
65+
for word in words.iter() {
66+
map.entry(word).or_insert(Term::new(0, 0)).inc_expect();
67+
}
68+
let mut result: Vec<i32> = Vec::new();
69+
// we can split terms in N ways, where N = word_len
70+
for shift in 0..word_len {
71+
let mut i = shift;
72+
let mut j = shift;
73+
// we do a sliding window for each round
74+
while j + word_len - 1 < s.len() {
75+
match map.entry(&s[j..j+word_len]) {
76+
Entry::Occupied(mut entry) => {
77+
entry.get_mut().inc();
78+
// term exhausted, shrink the window to release
79+
if entry.get().exhausted() {
80+
while i < j {
81+
let term = &s[i..i+word_len];
82+
map.entry(term).and_modify(|t| t.dec());
83+
i += word_len;
84+
if term == &s[j..j+word_len] { break }
85+
}
86+
j += word_len;
87+
} else {
88+
if j - i < (words.len() - 1) * word_len {
89+
j += word_len;
90+
} else {
91+
// matched!
92+
result.push(i as i32);
93+
// move the whole window, release the dropped term
94+
map.entry(&s[i..i+word_len]).and_modify(|t| t.dec());
95+
j += word_len; i += word_len;
96+
}
97+
}
98+
},
99+
// bad term, move over and do a reset
100+
Entry::Vacant(entry) => {
101+
map.iter_mut().for_each(|(_, v)| v.reset());
102+
j += word_len; i = j;
103+
},
104+
}
105+
}
106+
map.iter_mut().for_each(|(_, v)| v.reset())
107+
}
108+
result
109+
}
110+
}
111+
112+
// submission codes end
113+
114+
#[cfg(test)]
115+
mod tests {
116+
use super::*;
117+
118+
#[test]
119+
fn test_30() {
120+
assert_eq!(Solution::find_substring("barfoothefoobarman".to_string(), vec!["foo".to_string(),"bar".to_string()]),
121+
vec![0, 9]);
122+
assert_eq!(Solution::find_substring("wordgoodgoodgoodbestword".to_string(),
123+
vec!["word".to_string(),"good".to_string(), "best".to_string(), "word".to_string()]),
124+
vec![]);
125+
assert_eq!(Solution::find_substring("wordgoodgoodgoodbestword".to_string(),
126+
vec!["word".to_string(),"good".to_string(), "best".to_string(), "good".to_string()]),
127+
vec![8]);
128+
assert_eq!(Solution::find_substring("xxwordgoodgoodgoodbestword".to_string(),
129+
vec!["word".to_string(),"good".to_string(), "best".to_string(), "good".to_string()]),
130+
vec![10]);
131+
}
132+
}

0 commit comments

Comments
 (0)