日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

假币问题

發布時間:2023/12/18 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 假币问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文章:https://blog.csdn.net/qq_39630587/article/details/79243348

假幣問題

在八枚外觀相同的硬幣中,有一枚是假幣,并且已知假幣與真幣的重量不同,但不知道假幣與真幣相比較輕還是較重。可以通過一架天平來任意比較兩組硬幣,設計一個高效的算法來檢測出這枚假幣。

我們先假設一個條件:已知假幣比真幣輕

二分查找算法實現:時間復雜度(O(log(以2為底n的對數)))

思路:把n枚硬幣分成兩堆,每堆有枚硬幣,如果n為奇數的話,就留下一枚額外的硬幣,然后把兩堆硬幣放在天平上。如果兩堆硬幣重量相同,那么放在旁邊的硬幣就是假幣;否則我們可以用同樣的方式對較輕的一堆硬幣進行處理,這堆硬幣中一定包含那枚假幣。注意,即使我們把硬幣分成了兩個子集,但在每次稱重之后,我們只需要解決一個規模為原來一半的問題。所以這是一個減治算法而不是一個分治算法。

public class Main {static int[] a = {2, 2, 2, 2, 2, 2, 1, 2};public static void main(String[] args) {int l = 0;int r = a.length-1;System.out.println(f2(l, r));}private static int f2(int l, int r) {int n = r - l + 1;int mid = (l+r) / 2;if(n == 1) {return l;}/*** n為總個數,mid為中值* n為偶數,則將n枚硬幣分成兩堆數量相等的硬幣,對輕的一堆迭代稱重* n為奇數,留下一枚硬幣,對n-1枚硬幣按偶數繼續操作* */if (n % 2 == 0) {if (sum(l, mid) == sum(mid+1, r)) {return l - 1;} else if (sum(l, mid) < sum(mid+1, r)){return f2(l, mid);} else {return f2(mid+1, r);}} else {return f2(l+1, r);}}/*** 獲取指定區域內硬幣的重量* */private static int sum(int l, int r) {int sum = 0;for (int i = l; i <= r; i++) {sum += a[i];}return sum;} }

三分查找算法實現:時間復雜度(O(log(以3為底n的對數)))
思路:將n枚硬幣分成三組,前兩組有組硬幣,其余的硬幣作為第三組,將前兩組硬幣放到天平上,如果它們的重量相同,則假幣一定在第三組中,用同樣的方法對第三組進行處理;如果前兩組的重量不同,則假幣一定在較輕的那一組中,用同樣的方法對較輕的那組硬幣進行處理。這也是一個減治算法。

public class Main {static int[] a = {2, 2, 2, 2, 2, 2, 1, 2};public static void main(String[] args) {int l = 0;int r = a.length-1;System.out.println(f3(l, r));}private static int f3(int l, int r) {int n = r - l + 1;int x;if(n == 1) {return l;}/*** n為總個數* 將n分成n/3, n/3, n-2(n/3)三堆硬幣* 對前兩堆稱重,相等則對第三堆繼續操作,不相等則對輕的一堆繼續操作* */if (n % 3 == 0) {x = n / 3;} else {x = n / 3 + 1;return f3(l+1, r);}int mid1 = l + x - 1;int mid2 = mid1 + x;if (sum(l, mid1) == sum(mid1+1, mid2)) {return f3(mid2+1, r);} else if (sum(l, mid1) < sum(mid1+1, mid2)){return f3(l, mid1);} else {return f3(mid1+1, mid2);}}/*** 獲取指定區域內硬幣的重量* */private static int sum(int l, int r) {int sum = 0;for (int i = l; i <= r; i++) {sum += a[i];}return sum;} }

二分查找算法適用于單調的一個函數,即數組序列要么升序,要么降序

而三分查找算法使用于凸函數,常用來求極值問題。

在假幣問題中,三分查找在n較大的情況下,效率是優于二分查找的。

最復雜的情況

下面來回到最開始的問題,在不知道假幣輕重的情況下,我們通過下面的算法來實現,其時間復雜度為O(log(以2為底n的對數))

相比來說,這種情況思考起來比較復雜,但是好在邏輯清楚,只要理解了思路,算法還是好實現的,下面我們來舉一個例子,假設有八枚硬幣,其中有一枚硬幣是假幣。但是我們不知道假幣是比真幣重還是輕。先把八枚硬幣編號,分別表示為a,b,c,d,e,f,g,h,從八枚硬幣中任取六枚a,b,c,d,e,f,在天平兩端各放三枚進行比較。假設a,b,c三枚放在天平的一端,d,e,f三枚放在天平的另一端,可能出現三種比較結果:

⑴ a+b+c>d+e+f

⑵ a+b+c=d+e+f

⑶ a+b+c<d+e+f

若a+b+c>d+e+f,可以肯定這六枚硬幣中必有一枚為假幣,同時也說明g、h為真幣。這時可將天平兩端各去掉一枚硬幣,假設去掉c、f,同時將天平兩端的硬幣各換一枚,假設硬幣b、e作了互換,然后進行第二次比較,比較的結果同樣可能有三種:

① a+e>d+b:這種情況表明天平兩端去掉硬幣c、f且硬幣b、e互換后,天平兩端的輕重關系保持不變,從而說明了假幣必然是a,d中的一個,這時我們只要用一枚真幣(例如h)和a進行比較,就能找出假幣。若a>h,則a是較重的假幣;若a=h,則d為較輕的假幣;不可能出現a<h的情況。(為什么?很簡單,因為我們判斷了a,d中有一個假幣那么e,b都是真幣,則e=d。而a+e>d+b可以推出a>d,所以不管a是真是假都不可能出現a<h情況出現)

② a+e=d+b:此時天平兩端由不平衡變為平衡,表明假幣一定在去掉的兩枚硬幣c,f中,同樣用一枚真幣(例如h)和c進行比較,若c>h,則c是較重的假幣;若c=h,則f為較輕的假幣;不可能出現c<h的情況。

③ a+e<d+b:此時表明由于兩枚硬幣b,e的對換,引起了兩端輕重關系的改變,那么可以肯定b或e中有一枚是假幣,同樣用一枚真幣(例如h)和b進行比較,若b>h,則b是較重的假幣;若b=h,則e為較輕的假幣;不可能出現b<h的情況。

public class Main {static int[] a = {2, 2, 2, 2, 2, 2, 1, 2};static int flag = 0;public static void main(String[] args) {int p;if (sum(0, 2) == sum(3, 5)) {p = fp(6, 7);} else if (sum(0, 2) > sum(3, 5)){if (a[0] + a[4] > a[3] + a[1]) {p = fp(0, 3);} else if (a[0] + a[4] == a[3] + a[1]) {p = fp(2, 5);} else {p = fp(1, 4);}} else {if (a[0] + a[4] > a[3] + a[1]) {p = fp(1, 4);} else if (a[0] + a[4] == a[3] + a[1]) {p = fp(2, 5);} else {p = fp(0, 3);}}if (flag == 1) {System.out.println("假幣輕,為第" + p + "枚");} else {System.out.println("假幣重,為第" + p + "枚");}}private static int fp(int l, int r) {int H, L;int x = (l+1) % 8;if(a[l] > a[r]) {H = l;L = r;} else {H = r;L = l;}if (a[H] > a[x]) {flag = 1;return H;} else {flag = -1;return L;}}/*** 獲取指定區域內硬幣的重量* */private static int sum(int l, int r) {int sum = 0;for (int i = l; i <= r; i++) {sum += a[i];}return sum;} }

總結

以上是生活随笔為你收集整理的假币问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。