1. 程式人生 > 其它 >2022-4-21 二分查詢

2022-4-21 二分查詢

392. 判斷子序列

給定字串 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 }

思路:指標搜尋。

 

793. 階乘函式後 K 個零

 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 }

思路:二分搜尋上下邊界。具體思路見註釋。