给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。 如果不存在符合条件的子数组,返回 0 。
示例 1:
1 2 3 输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组[4,3] 是该条件下的长度最小的子数组。
示例 2:
1 2 输入:target = 4, nums = [1,4,4] 输出:1
示例 3:
1 2 输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 104
进阶:
如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。
💡 思路:
暴力破解 两个循环,不断的寻找符合条件的子序列,时间复杂度O(n^2) 可能超时
滑动窗口 不断的调节子序列的起始位置和终止位置,得出我们要的结果 ,时间复杂度为O(n)
代码(思路一):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 impl Solution { pub fn min_sub_array_len (target: i32 , nums: Vec <i32 >) -> i32 { let mut ans = i32 ::MAX; let n = nums.len (); for i in 0 ..n { let mut sum = 0 ; for j in i..n { sum += nums[j]; if sum >= target { ans = ans.min ((j - i + 1 ) as i32 ); break ; } if (j - i + 1 ) as i32 >= ans { break ; } } } if ans == i32 ::MAX { 0 } else { ans } } }
代码(思路二):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 impl Solution { pub fn min_sub_array_len (target: i32 , nums: Vec <i32 >) -> i32 { let mut ans = i32 ::MAX; let mut left = 0 ; let mut sum = 0 ; for right in 0 ..nums.len () { sum += nums[right]; while sum >= target { ans = ans.min ((right - left + 1 ) as i32 ); sum -= nums[left]; left += 1 ; } } if ans == i32 ::MAX { 0 } else { ans } } }
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
示例 1:
1 2 3 输入:fruits = [1,2,1] 输出:3 解释:可以采摘全部 3 棵树。
示例 2:
1 2 3 4 输入:fruits = [0,1,2,2] 输出:3 解释:可以采摘 [1,2,2] 这三棵树。 如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
示例 3:
1 2 3 4 输入:fruits = [1,2,3,2,2] 输出:4 解释:可以采摘 [2,3,2,2] 这四棵树。 如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。
示例 4:
1 2 3 输入:fruits = [3,3,3,1,2,1,1,2,3,3,4] 输出:5 解释:可以采摘 [1,2,1,1,2] 这五棵树。
提示:
1 <= fruits.length <= 105
0 <= fruits[i] < fruits.length
💡 思路: 问题可以转化为:在一个数组中,找到最长的连续子数组,其中最多包含两种不同的元素 使用滑动窗口 解决
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 use std::collections::HashMap;impl Solution { pub fn total_fruit (fruits: Vec <i32 >) -> i32 { let mut max_fruits = 0 ; let mut left = 0 ; let mut fruit_counts = HashMap::new (); for right in 0 ..fruits.len () { *fruit_counts.entry (fruits[right]).or_insert (0 ) += 1 ; while fruit_counts.len () > 2 { let left_fruit = fruits[left]; *fruit_counts.get_mut (&left_fruit).unwrap () -= 1 ; if fruit_counts[&left_fruit] == 0 { fruit_counts.remove (&left_fruit); } left += 1 ; } max_fruits = max_fruits.max (right - left + 1 ); } max_fruits as i32 } }
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
1 2 3 输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC" 解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例 2:
1 2 3 输入:s = "a", t = "a" 输出:"a" 解释:整个字符串 s 是最小覆盖子串。
示例 3:
1 2 3 4 输入: s = "a", t = "aa" 输出: "" 解释: t 中两个字符 'a' 均应包含在 s 的子串中, 因此没有符合条件的子字符串,返回空字符串。
提示:
m == s.length
n == t.length
1 <= m, n <= 105
s 和 t 由英文字母组成
进阶:
你能设计一个在o(m+n)时间内解决此问题的算法吗?
💡 思路:滑动窗口
使用HashMap记录t中出现的字符以及数量
定义左右边界,建立窗口
右边界右移,判断右边界字符是否存在于t中,结果记录到另一个HashMap 中
当两个哈希表相同时,找到符合的子序列
左边界右移,缩小窗口
代码(思路一):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 use std::collections::HashMap;impl Solution { pub fn min_window (s: String , t: String ) -> String { if s.is_empty () || t.is_empty () || s.len () < t.len () { return String ::new (); } let s_chars : Vec <char > = s.chars ().collect (); let t_chars : Vec <char > = t.chars ().collect (); let mut t_count = HashMap::new (); for &c in &t_chars { *t_count.entry (c).or_insert (0 ) += 1 ; } let required = t_count.len (); let mut formed = 0 ; let mut window_counts = HashMap::new (); let mut result = (usize ::MAX, 0 , 0 ); let mut left = 0 ; for right in 0 ..s_chars.len () { let c = s_chars[right]; if t_count.contains_key (&c) { *window_counts.entry (c).or_insert (0 ) += 1 ; if window_counts[&c] == t_count[&c] { formed += 1 ; } } while formed == required { let current_len = right - left + 1 ; if current_len < result.0 { result = (current_len, left, right); } let left_char = s_chars[left]; if t_count.contains_key (&left_char) { *window_counts.get_mut (&left_char).unwrap () -= 1 ; if window_counts[&left_char] < t_count[&left_char] { formed -= 1 ; } } left += 1 ; } } if result.0 == usize ::MAX { String ::new () } else { s_chars[result.1 ..=result.2 ].iter ().collect () } } }
优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 impl Solution { pub fn min_window (s: String , t: String ) -> String { let s_bytes = s.as_bytes (); let t_bytes = t.as_bytes (); if s.is_empty () || t.is_empty () || s.len () < t.len () { return String ::new (); } let mut cnt = [0 ; 58 ]; let mut required = 0 ; for &c in t_bytes { let idx = (c - b'A' ) as usize ; if cnt[idx] == 0 { required += 1 ; } cnt[idx] += 1 ; } let (mut left, mut min_len, mut start) = (0 , usize ::MAX, 0 ); let mut formed = 0 ; for right in 0 ..s_bytes.len () { let right_char = s_bytes[right]; let idx = (right_char - b'A' ) as usize ; cnt[idx] -= 1 ; if cnt[idx] == 0 { formed += 1 ; } while formed == required { let current_len = right - left + 1 ; if current_len < min_len { min_len = current_len; start = left; } let left_char = s_bytes[left]; let left_idx = (left_char - b'A' ) as usize ; cnt[left_idx] += 1 ; if cnt[left_idx] > 0 { formed -= 1 ; } left += 1 ; } } if min_len != usize ::MAX { s[start..start + min_len].to_string () } else { String ::new () } } }