2022-4-21 二分查找

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace""abcde"的一个子序列,而"aec"不是)。

进阶:

如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

 1 class Solution {
 2     public boolean isSubsequence(String s, String t) {
 3         int l=0;
 4         for (int i=0;i<s.length();i++){
 5             while (l<t.length()&&s.charAt(i)!=t.charAt(l)){
 6                 l++;
 7             }
 8             if (l<t.length()){
 9                 l++;
10                 continue;
11             }
12             else return false;
13         }
14         return true;
15     }
16 }

思路:指针搜索。

 

 f(x) 是 x! 末尾是 0 的数量。回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 。

  • 例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 ;而 f(11) = 2 ,因为 11!= 39916800 末端有 2 个 0 。

给定 k,找出返回能满足 f(x) = k 的非负整数 x 的数量。

 1 class Solution {
 2     public int preimageSizeFZF(int k) {
 3         // f(x)应该是一个非递减函数
 4         // 答案就是左右边界的差
 5         //二分查找左右边界
 6         // x取到5000000000L k基本上为10^9
 7         long left=0L,right=5000000000L;
 8         // 左边界
 9         while (left<right) {
10             long mid=(left+right)/2;
11             if ((int)f(mid)>k){
12                 right=mid;
13             }else if ((int)f(mid)<k){
14                 left=mid+1;
15             }else {
16                 right=mid;
17             }
18             System.out.println(left+" "+right);
19         }
20         long left_bound=left;
21         left=0L;
22         right=5000000000L;
23         // 右边界,取到右边界必须相等。
24         while (left<=right) {
25             long mid=(left+right)/2;
26             if ((int)f(mid)==k){
27                 left=mid+1;
28             }else if((int)f(mid)<k){
29                 left=mid+1;
30             }else{
31                 right=mid-1;
32             }
33             //System.out.println(left+" "+right);
34         }
35         long right_bound=right;
36         //System.out.println(left_bound+" "+right_bound);
37         //System.out.println(f(left_bound)+" "+f(right_bound));
38         //System.out.println(f(left_bound-1)+" "+f(right_bound+1));
39         if (left_bound<=right_bound+1) return (int)(right_bound-left_bound+1);
40         else return 0;
41 
42 
43     }
44 
45 
46     public long f(long x){
47         // 因数 2 5 相乘才会有0
48         // 且2 的数量肯定比5多
49         // fx为1~x中 5的因数的数量
50         long res=0L,pow=5L;
51         while (x>=pow){
52             res+=(x/pow);
53             pow*=5;
54         }
55         return res;
56     }
57 }

思路:二分搜索上下边界。具体思路见注释。

posted on 2022-04-21 14:50  阿ming  阅读(22)  评论(0)    收藏  举报

导航