leetcode:Minimum Window Substring

题目大意:在一个字符串S中找一个最短子串,使得这个最短子串中包含另外一个字符串T中的所有字符。

解法:

 首先向这种乍一看似乎是n^2复杂度,且又必须通过线性时间复杂度来完成的问题一般都可以利用动态规划来解决。但是这里并不是直接使用动态规划,而是使用动态规划的思路,复用前面的结果来计算剩余部分。

  假设S[i...j]是所有以i起始包含T中所有字符的子串中的最短者,我们称j是i的右界。若j是i的右界,那么i+1的右界必然不可能小于j。因为若i+1的右界k<j,则S[i+1...k]也是包含字符串T的一个S的子串,那么S[i...k]中包含了S[i+1...k]中的所有字符,因此S[i...k]也是包含字符串T的一个S的子串,这与j是i的右界的定义相悖,故假设不成立,从而命题得证。

  因此我们只需要维护两个下标i和j,j作为i可能的右界,显然在i递增的前提下可以同样推出j不减,因此只要保证每次循环或许增大i或者增大j,就可以以线性时间得到结果。

  具体的流程是创建一个需求表D,需求表中保存的键值对k:v,表示S[i...j]要包含T还缺少v个字符k。因此每次增加i后,先令D[S[i-1]]自减,之后不断增大j,每次增大j后都需要令D[S[j-1]]自增,直到D中所有的项都不超过0,这样就能保证j是i的右界。至于如果能快速判断D中所有项不超过0,可以通过一个计数器counter,counter记录当前D中大于0的项的个数,之后不断检测counter即可。


实现:
 1 class Solution {
 2     int[] need;
 3     int counter;
 4     public String minWindow(String s, String t) {
 5         need = new int[256];
 6         counter = 0;
 7         for(int i = 0, bound = t.length(); i < bound; i++)
 8         {
 9             char c = t.charAt(i);
10             if(need[c] == 0)
11             {
12                 counter++;
13             }
14             need[c]++;
15         }
16         
17     
18         int minL = -1;
19         int min = Integer.MAX_VALUE;
20         for(int l = 0, r = 0, bound = s.length(); l < bound; l++)
21         {
22             while(counter > 0 && r < bound)
23             {
24                 add(s.charAt(r));
25                 r++;
26             }
27             
28             if(counter > 0)
29             {
30                 break;
31             }
32             if(r - l < min)
33             {
34                 min = r - l;
35                 minL = l;
36             }
37             delete(s.charAt(l));
38         }
39         
40         if(minL < 0)
41         {
42             return "";
43         }
44         return s.substring(minL, minL + min);
45     }
46     
47     private void delete(char c)
48     {
49         if(need[c] == 0)
50         {
51             counter++;
52         }
53         need[c]++;
54     }
55     private void add(char c)
56     {
57         if(need[c] == 1)
58         {
59             counter--;
60         }
61         need[c]--;
62     }
63 }
View Code

 

转载于:https://www.cnblogs.com/dalt/p/7695745.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值