百人開燈問題解法及優化
一:題意
房間裡有100盞電燈,編號為1,2,3……100,每盞燈上有一個按鈕,初始時燈全都是關的。編好號的100位同學由房間外依次走進去,將自己編號的倍數的燈的按鈕全部按一次
- 第一位同學把編號是1的倍數的燈的按鈕按一下(此時100盞燈全亮)
- 第二位同學把編號是2的倍數的燈的按鈕按一下(此時只有50盞燈亮著,50盞被這個人按滅了
- ……
- 第100位同學把編號是100的倍數的燈(即編號為100的燈)的按鈕按一下
請問依次走完後,還有多少盞燈亮著?
二:實現
1:暴力法
-
雙迴圈暴力破解
-
時間複雜度:O(n*n)
-
空間複雜度:O(1)
-
程式碼實現:
/**
* 暴力法
* 時間複雜度:O(n*n)
*/
public class Test {
public static void main(String[] args) {
int[] light = new int[101];
//初始化為燈關閉
for (int i = 1; i < light.length; i++) {
light[i] = 0;
}
//關燈操作
for (int i = 1; i < light.length; i++) {
for (int j = 1; j < light.length; j++) {
if(j%i == 0) {
light[j] = light[j] == 0 ? 1 : 0;
}
}
}
//輸出開啟的燈
for (int i = 1; i < light.length; i++) {
if(light[i] == 1)
System.out.println(i);
}
/**
* 輸出
* 1
* 4
* 9
* 16
* 25
* 36
* 49
* 64
* 81
* 100
*/
}
}
2:優化一:
-
觀察發現每一盞燈都只會被比自身小並且是自身約數的值和自身 進行開啟或者關閉操作
-
我們將自身數對燈的開啟關閉排除,則比這盞燈小並且是這盞燈約數的值為偶數,則最後為開燈,否則最後為熄燈
-
時間複雜度會比單純的暴力法降低一些
-
程式碼如下:
/**
* 優化暴力法
* 時間複雜度:O(n*n),但會比單純的暴力法時間複雜度低
*/
public class Test {
public static void main(String[] args) {
int[] light = new int[101];
//初始化為燈關閉
for (int i = 1; i < light.length; i++) {
light[i] = 0;
}
//關燈操作
for (int i = 1; i < light.length; i++) {
for (int j = 1; j < i; j++) {
if(i%j == 0) {
light[i]++;
}
}
}
//輸出開啟的燈
for (int i = 1; i < light.length; i++) {
if(light[i]%2 == 0)
System.out.println(i);
}
/**
* 輸出
* 1
* 4
* 9
* 16
* 25
* 36
* 49
* 64
* 81
* 100
*/
}
}
3:優化二:
-
觀察發現,每盞燈都會被“1”操作一次,也會被自身的值操作一次,這兩次相互抵消
-
對於燈i,如果存在一個i的約數j,那麼一定存在另外一個約數k,如果j != k ,那麼這兩次相互抵消,如果j == k,那麼只有一個這樣的值,不會被抵消,這樣只有存在完全約數(比如:4 = 2*2 , 9 = 3*3類的)的燈才不會被抵消,所以我們要求的就是具有完全約數的值。
-
所以我們只要判斷值的開方是不是整數就可以了
-
時間複雜度:O(n)
-
沒有通用性,程式碼如下:
/**
* 具體問題具體分析,沒有通用性
* 時間複雜度:O(n)
*/
public class Test {
public static void main(String[] args) {
int[] light = new int[101];
//初始化為燈關閉
for (int i = 1; i < light.length; i++) {
light[i] = 0;
}
//關燈操作並輸出
for (int i = 1; i < light.length; i++) {
double k = Math.sqrt(i);
int m = (int)k;
if((double)m == k) {
System.out.println(i);
}
}
/**
* 輸出
* 1
* 4
* 9
* 16
* 25
* 36
* 49
* 64
* 81
* 100
*/
}
}
相關文章
- 問題 F: 開燈問題(第二講)
- 運籌優化(六)--目標規劃定義及解法優化
- MySQL資料庫開發常見問題及幾點優化!MySql資料庫優化
- 八皇后問題python解法Python
- 凸優化問題優化
- SpringCloud之Eureka的常見問題及配置優化SpringGCCloud優化
- RMQ問題的各種解法MQ
- 斜率優化(凸包優化)DP問題acm優化ACM
- 10元買啤酒問題Java解法Java
- Swift 首次除錯斷點慢的問題解法 | 優酷 Swift 實踐Swift除錯斷點
- 03-凸優化問題優化
- 數值最優化—優化問題的解(二)優化
- 幾數之和分析,解法,優化和總結優化
- TensorFlow系列專題(九):常用RNN網路結構及依賴優化問題RNN優化
- 多路口交通燈問題
- 【離散優化】覆蓋問題優化
- N皇后問題(各種優化)優化
- go的編譯優化問題Go編譯優化
- 記一個效能優化問題優化
- 決策樹減支問題(優化)dfs減支問題優化
- 如何解決百人研發團隊的管理問題?
- [20211210]優化遇到的奇怪問題.txt優化
- [20181119]使用sql profile優化問題.txtSQL優化
- webpack dll打包重複問題優化Web優化
- iOS問題整理08----效能優化iOS優化
- ArrayList 原始碼分析 — 擴容問題及序列化問題原始碼
- ArrayList 原始碼分析 -- 擴容問題及序列化問題原始碼
- 01揹包和完全揹包問題解法模板
- MySQL問題定位-效能優化之我見MySql優化
- RecyclerView使用,優化,條目閃爍問題View優化
- 關於vue的webpack打包優化問題VueWeb優化
- 記錄一些常見問題的不同解法
- 資料庫sql的優化問題的面試題資料庫SQL優化面試題
- mpvue開發小程式所遇問題及h5轉化方案VueH5
- 記一次Prometheus代理效能優化問題Prometheus優化
- hoj 1070 圖的m可著色優化問題優化
- 優化GAN的分佈的梯度問題,WGAN優化梯度
- Android整合React Native啟動白屏問題優化AndroidReact Native優化