1. 程式人生 > >程式設計之美----擴充套件問題

程式設計之美----擴充套件問題

參考連結:

1.1 讓CPU佔用率曲線聽你指揮

參考:

http://blog.csdn.net/wesweeky/article/details/6402564

http://www.cnblogs.com/chenyuming507950417/archive/2012/09/14/2685097.html

1.2 中國象棋將帥問題

解法二用進位制的方法好理解一些,但以下參考中有人用多重迴圈轉換的方式解釋也可以理解

參考:

http://book.douban.com/annotation/13753057/

http://blog.csdn.net/kabini/article/details/2256421

http://blog.csdn.net/silenceburn/article/details/6133222

1.3 一摞烙餅的排序

遞迴遍歷+上界下界剪枝+狀態記錄

擴充套件問題:

1多了一個腦袋可以放餅,速度肯定會加快,基本思路是將餅堆分為兩部分,第一部分中最大值小於第二部分(或第一部分最小值大於第二部分,或者這樣說,第一部分是大小是123,第二部分是456,只是都亂序),然後兩部分分別排序,最後再合併

2

A  先按照“烙餅排序實現”對烙餅進行大小排序 
B  然後對有金黃色不朝上的烙餅做如下操作,以cakeArray[k]為例 
翻轉cakeArray[0:k],將cakeArray[k]翻到頂層,翻轉cakeArray[k],然後將cakeArray[0:k]翻轉,將cake[k]翻回原來位置 

3概率是2/3

4可以猜測出將會優先把最上面的部分有序,逐漸到下面形成有序,具體的規則沒有想到,程式碼仍然是遍歷,只是將次數作界限改為翻轉餅個數

5最大下辦15N/14,最小上界(5N+5)/3

第14個烙餅數P14=?

1.4 買書問題

參考:

http://blog.csdn.net/kabini/article/details/2296943 // 注意評論 第6樓舉的例子

貪心演算法與動態規劃的理解

此問題貪心演算法不適用(或者暫時未找到合適的貪心演算法)

動態規劃時間複雜度為O(Y1*Y2*Y3*Y4*Y5)// by zjerry 如何理解這個?

1.5 快速找出故障機器

利用O(1)空間解決唯一ID值不同的問題,需要用到異或的特性,連續異或可以理解為位的連續求異存同(其實是求奇棄偶),最終得到的值就是唯一ID值(沒有相同的ID與他相同得到0)

兩個不同值根據異或結果某一位上的1,將原ID集合分為兩類,該位上有1和無1,再分別連續異或

另解法:構造方程,求一個值,利用原正常ID構造和,然後減去現有,剩下值即為所求;求兩個值,可以構造x+y,x^2+y^2

擴充套件問題:

3個值或3個以上的情況下可以考慮構造方程,

也可以考慮用hashMap儲存ID,然後過濾正常ID

撲克問題:用原和減去剩下的和

1.6 飲料供貨

動態規劃

貪心

參考:http://blog.csdn.net/lichaoyin/article/details/9983883

動態規劃思路基本上是揹包問題

貪心演算法利用到了進位制分解,將容量以二進位制看待,設計資料結構:每一位後有一條最大值連結串列,演算法:從低位到高位,該位需要容量填充時就從每一位後的有序連結串列中得到滿意度最大的若干容量相加,計算之前先將上一個低位的最大值合併到新的連結串列中(有些類似哈夫曼樹的構造過程?)

1.7 光影切割問題

解法一:分析出每增加一直線,如果增加m個交點,那麼該直線被新增加的m個交戰分成m+1段,每一段又會將原區域劃成兩塊,於是新增加了m+1塊

如果有n條直線,m個交點,那麼區域數為n+m+1,求解過程是1+求和(m0+1)=1+n條直接的全部交點和+n=1+m+n  // 因為每次增加m0+1,n個點求和

切割塊數先將所有點的交點求出來,然後排序,鎖定AB之間的點(二分查詢),再利用1+n+m計算出塊數

解法二:

區域內的交戰數目等於一個邊界上交點順序相對另一個邊界交點順序的逆序總數,求逆序數利用分治法可以優化到O(n*logn)

// by zjerry 這個轉換過程沒完全理解,為什麼逆序數會=交點數?

1.8 小飛的電梯除錯演算法

如何從O(N^2)優化到O(N)的關鍵是找到遍歷過程相鄰之間的增減關係

擴充套件問題

1仍然用書中的解法二,O(N)時間內解決,

2// by zjerry 還要再想想

1.9 高效率地安排見面會

原問題是NP的經典問題 地圖著色

擴充套件問題:

1.基於時間軸的活動地點選擇問題,由於可以向一維時間軸投影,所以可以使用貪心演算法

書中O(N^2)解法沒仔細理解(應該是類似著色判斷是否合理的演算法),

主要理解第二個解法:直接計算某區間最大重疊次數,如果利用計數排序+一次MAX值掃描,可以優化到O(N)  // by zjerry

2.問題的前提還是在優化總的時間基礎上,因此只能原問題的基礎上擴張結構以實現集中

我的想法是,同學對見面會的興趣度可以理解為圖中的邊的權重,讓每個都集中也就是總體集中

頂點著色數量設計好後,頂點起始時間排序,起始時間相同則按照上一頂點與欲選擇頂點的興趣度排序,最後得到結果

1.10 雙執行緒高效下載

// by zjerry 訊號量,互斥鎖



1.11 NIM(1)一排石頭的遊戲

註明A先取,B後取

擴充套件

1.N=3K+1(K=0,1,2,……)時先取者A輸,其餘情況N=3K,N=3K+2時先取者A贏

2.N%(K+1)=0時,玩家B有必勝策略,N%(K+1)!=0時,玩家A有必勝策略。

當d=0時,無論A取多少個石頭,B取相應的石頭,使得A和B一起取(K+1)個石頭,這樣最後取到石頭的肯定是玩家B。

1.12 NIM(2)"拈"遊戲分析

註明A先分配,B先取,A後取

取石頭的過程與上一次他人取的數目始終保持一個"安全的狀態",即可以確保完勝,這裡安全的狀態是XOR為0

擴充套件問題

1如果取光者輸,當N=2,B先取,A必輸,N>2,A必勝,只要確保堆數為奇,個數也為奇即可,N為奇數,則分配(1,1,1,...),N為偶數,則分配(N/2,N/2)

2若是先取光者勝,則A保持安全狀態為每次取走和為K+1(與1.11擴充套件問題類似),且每堆的個數為>=2(關鍵是取到只剩下K+1,K+2...K+K-1堆時的抉擇問題上)

// by zjerry 未仔細認證,先到這裡

1.13 NIM(3)兩堆石頭的遊戲

注意A先取, B後取,AB可以兩堆中各拿相等數量的石頭或從一堆中取走任意

擴充套件

1.A先取始終構造不安全局面給B,即可確保必勝(前提是初始狀態為安全)

2.NIM(4)

1.14 連連看遊戲設計

擴充套件問題:

1.維護任意兩個格子的最短路徑的優點是,每次重新整理最短路徑資料後都能迅速判斷,但重新整理資料的過程會比較麻煩,因為連連看消去後牽扯的格子並不能立即確定出來,很大可能要維護重新整理所有格子,則N*O(N)複雜度,效率不一定高,

遊戲中是否用點選觸發的範圍修改還是全域性維護資料修改,這類問題類似於動態查詢樹如紅黑樹,二叉堆,能否在O(logn)可接受的時間範圍內解決問題

2.每執行完一步下棋操作後,用某種資料結構儲存當前棋局,如壓縮矩陣,鄰接矩陣,點陣圖等

1.15 構造數獨

擴充套件問題:

如何表示桌面程式中的視窗/按鈕/控制元件?// by zjerry 我一般想到的是制定合理的座標系,如右x下y外z,然後每個視窗的屬性有左上角座標xy,長length,寬width,z軸z-order,能否點選clickable,性質(window,button,widget,etc)

1.16 24點遊戲

解法一:窮舉遞迴   優化:剪枝,加法和乘法滿足交換律,swap使A>B或A<B來進行加乘法的計算

解法二:集合的分治求解  優化:最後一次兩個子集合並直接計算判斷是否24點,不用再進行集合合併後再判斷;依照解法一,每次取兩個數計算然後合併集合(按書中每次按1,n-1來分解集合,分解集合的過程太多)

1.17 俄羅斯方塊遊戲

擴充套件問題

1.需要DFS記錄移動路徑

2.OFFSETY增加2格,則OFFSETX的判斷範圍減少3

3.俄羅斯廣場是消除類遊戲,優先考慮消除(使遊戲更輕鬆),如新增子彈方塊,新增爆炸方塊,新增消除方塊;再考慮增長(使遊戲更困難),如新增變形方塊,新增移動加速,新增下落後的方塊會自動向上增長,且帶小洞,自動左右迴圈,初始帶有小洞的層次,

非遊戲功能上的擴充套件可以有:積分社交排行功能,二人PK,線上PK,且PK帶有戰鬥模式,A方消除造成B方增長

掃雷遊戲是判斷類遊戲,優先考慮降低難度,如增加提示,減少雷數,再考慮增加難度,如可改變格子數目,可調整雷數,時間縮短,雷有輕重緩急的等級,

非遊戲功能上的擴充套件積分社交排行,二人PK,互相設定對方的雷區等

1.18 挖雷遊戲

參考:

http://blog.csdn.net/wuyuegb2312/article/details/9302915

問題1

需要先解決問題2

問題2

1.根據已有數字將確定有雷和無雷的地區標記出來,然後將確定有雷的8鄰區計數-1,清除該塊,將確定無雷的8鄰區計數+1,清除該塊,依次解決出已點出區域的鄰區

2.步驟1解決後,可確定雷數已知,然後利用已知區域相交的結合點來劃分子雷區,再根據古典概率計運算元雷區的每個點的概率

參考4.11 掃雷遊戲的概率

2.1求二進位制中1的個數

解法:
1,v模2的值是1則++;
2,v右移(相當於除2),然後與0x1與運算(與上一解法思路一致);
3,v與v-1進行與運算,將消去最右邊的1,迴圈進行下去,時間複雜度只有O(n) n=1的個數;
4,查表的複雜度為O(1),不過要考慮建表的時間
針對該問題,有規律進行快速建表:
5,根據奇偶性來分析,對於任意一個正整數n
1.如果它是偶數,那麼n的二進位制中1的個數與n/2中1的個數是相同的,比如4和2的二進位制中都有一個1,6和3的二進位制中都有兩個1。為啥?因為n是由n/2左移一位而來,而移位並不會增加1的個數。
2.如果n是奇數,那麼n的二進位制中1的個數是n/2中1的個數+1,比如7的二進位制中有三個1,7/2 = 3的二進位制中有兩個1。為啥?因為當n是奇數時,n相當於n/2左移一位再加1。

http://blog.csdn.net/justpub/article/details/2292823
http://www.cnblogs.com/graphics/archive/2010/06/21/1752421.html 

6.二分法,或三個一組的位操作方法

SSE4.2:POPCNT指令演算法
http://en.wikipedia.org/wiki/Hamming_weight

HAKMEM演算法

   1:  int Count(unsigned x) {
   2:     unsigned n;    
   3:      
   4:     n = (x >> 1) & 033333333333;    
   5:     x = x - n;   
   6:     n = (n >> 1) & 033333333333;   
   7:     x = x - n;    
   8:     x = (x + (x >> 3)) & 030707070707;   
   9:     x = modu(x, 63);  
   10:     return x;   
   11:  } 

或寫成

  1. int BitCount5(unsigned int n)   
  2. {  
  3.     unsigned int tmp = n - ((n >>1) &033333333333) - ((n >>2) &011111111111);  
  4.     return ((tmp + (tmp >>3)) &030707070707) %63;  
  5. }  


擴充套件

問題一是問32位整型如何處理,用HAKMEM演算法,建表,或相與的方法都合適。

問題二是給定兩個整數A和B,問A和B有多少位是不同的。

只要先算出A和B的異或結果,然後求這個值中1的個數就行了。




這個問題其實就是數1問題多了一個步驟,只要先算出A和B的異或結果,然後求這個值中1的個數就行了。

2.2不要被階乘嚇倒

1.求N!末尾有多少個0
解法:
求質因數5的個數
其中有公式N!階乘中含有K的質因數個數 Z=[N/K]+[N/K^2]+[N/K^3]+...
2.求N!二進位制最低位1的位置
解法:同上
求質因數2的個數+1(末尾有多少個0再+1位就是最低位1的位置)
同樣使用公式Z
解法2:公式Z轉化二進位制後可以換算=N減去N的二進位制中1的個數

相關題目:

給定整數,判斷是否是2的方冪

即n>0&&(n&(n-1)==0)  // 該數二進位制表示法只有一個1

2.3尋找發帖水王

尋找可重複資料中出現次數超過一半的項
http://www.cnblogs.com/sooner/archive/2013/04/02/2996589.html
解法一:先排序,然後N/2的項即為所求
解法二:每次去除兩個不同ID項,最後得到的即為所求,O(N)

  1. int find(int ID[], int n)  
  2. {  
  3.     int nTimes = 0, i, candidate;  
  4.     for(i = 0; i < n;i++)  
  5.     {  
  6.           if(nTimes == 0)  
  7.           {  
  8.               candidate = ID[i];  
  9.               nTimes = 1;  
  10.           }  
  11.           else
  12.           {  
  13.               if(candidate == ID[i])  
  14.               {  
  15.                   nTimes++;  
  16.               }  
  17.               else
  18.               {  
  19.                   nTimes--;  
  20.               }  
  21.           }  
  22.     }  
  23.     return candidate;  
  24. }  
缺點是無法同時得到該項次數
解法三:HASH統計,空間複雜度O(N),解法二是O(1)

擴充套件問題
已知有M個發帖量在1/(M+1)個以上的ID


例子:
擴充套件題,題目如下:
隨著Tango的發展,管理員發現,“超級水王”沒有了。統計結果表明,有3個發帖很多的ID,他們的發帖數目都超過了帖子總數目N的1/4。你能從發帖ID列表中快速找出他們的ID嗎?


同時刪除4個不同的ID後,剩餘資料中3個多數id仍然是多數ID。


上題只需要一個結果,而現在需要3個結果,上題用到的nTimes,也應改為3個計數器。現在我們需要3個變數來記錄當前遍歷過的3個不同的ID,而nTimes的3個元素分別對應當前遍歷過的3個ID出現的個數。如果遍歷中有某個ID不同於這3個當前ID,我們就判斷當前3個ID是否有某個的nTimes為0,如果有,那這個新遍歷的ID就取而代之,並賦1為它的遍歷數(即nTimes減1),如果當前3個ID的nTimes皆不為0,則3個ID的nTimes皆減去1。

  1. #include <iostream>
  2. usingnamespace std;  
  3. int candidate[3];  
  4. int count[3] = {0};  
  5. int input[100];  
  6. int num = 0;  
  7. int main()  
  8. {  
  9.     cout<<"please input"<<endl;  
  10.     int t;  
  11.     while(cin>>t)  
  12.     {  
  13.         if (t == -1)  
  14.             break;  
  15.         input[num++] = t;  
  16.     }  
  17.     bool flag = false;  
  18.     for (int i = 0;i < num;i++)  
  19.     {  
  20.         flag = false;  
  21.         for (int j = 0;j < 3;j++)  
  22.         {  
  23.             if (count[j] == 0)  
  24.             {  
  25.                 continue;  
  26.             }  
  27.             if (candidate[j] == input[i])  
  28.             {  
  29.                 count[j]++;  
  30.                 flag = true;  
  31.             }  
  32.         }  
  33.         if (flag == true)  
  34.         {  
  35.             continue;  
  36.         }  
  37.         for (int j = 0;j < 3;j++)  
  38. 相關推薦

    程式設計----擴充套件問題

    參考連結: 1.1 讓CPU佔用率曲線聽你指揮 參考: http://blog.csdn.net/wesweeky/article/details/6402564 http://www.cnblogs.com/che

    程式設計 求陣列的子陣列之和的最大值(包含擴充套件問題解答)

    本程式碼可以通過以下測試用例: 陣列:[1,-2,3,5,-3,2] 返回:8 陣列:[0,-2,3,5,-1,2] 返回:9 陣列:[-9,-2,-3,-5,-3] 返回:-2 程式碼清單如下: #include <iostream> using namesp

    程式設計1.8小飛的電梯排程演算法擴充套件問題

    設有N2個乘客在第i層下,N1個乘客的目的地樓層在第i層以下,N3個乘客的樓層在第i層以上 假設電梯從停在i層改停在為i+1層,停在第i層時消耗的總能量為E 則改為i+1層停之後原先i層以上的乘客即N3個乘客少往上爬一層,原先第i層的N2個乘客需多往下爬一層,原先第i層以下

    程式設計——一摞烙餅的排序(暴搜+剪枝)

    題目 分析 深度優先搜尋遍歷每一種情況,去翻轉次數最小的,當然,還要加一些剪枝,畢竟O(nn)的時間複雜度。 程式碼 C風格 1 /**** 字首排序 ****/ 2 #include<stdio.h> 3 #include<cstring> 4 #incl

    程式設計10:計算字串的相似度

    我們並不在乎兩個字串變得相等之後的字串是怎樣的,所以 1.一步操作之後,再將A[2,…,lenA]和B[1,…,lenB]變成相同的字串。 2.一步操作之後,再將A[1,…,lenA]和B[2,…,lenB]變成相同的字串。 3.一步操作之後,再將A[2,…,lenA]和B[2,…,lenB]變成相

    程式設計9:陣列迴圈位移

    1: RightShift(int *arr, int N, int K) { K %= N; while (K--) { int t = arr[N - 1]; for (int i = N - 1; i > 0; i--)

    程式設計8:求陣列的子陣列之和的最大值

    1: int MaxSum(int *A, int n) { int maximum = -INF; int sum; for (int i = 0; i < n; i++) { sum = 0; for (int j = i;

    程式設計7:最大公約數

    1:輾轉相除法 f(x,y) = f(y, x%y); int gcd(int x, int y) { return (!y) ? x : gcd(y, x % y); } 2:對於大整數,取模運算非常昂貴。 f(x, y) = f(x-y, y); BigInt gcd(BigI

    程式設計3:求二進位制數中1的個數

    1: int Count(BYTE v) { int num = 0; while (v) { if (v % 2 == 1) { num++; } v = v / 2; }

    程式設計2:程式只用一個位元組變數,列印將帥位置

    原創:https://blog.csdn.net/ndzjx/article/details/84404320 #include <stdio.h> #include <windows.h> #include <time.h> #include <

    程式設計1:CPU列印直線,曲線

    原創:https://blog.csdn.net/ndzjx/article/details/84404268 1:本質:每次迴圈的CPU比例問題。 CPU排程時間片,大約為20ms 2.2GHz是CPU時鐘週期,= 22億次 = 2.2*10^9 每個時鐘週期平均執行2條彙編指令

    程式設計4:階乘相關

    1)N!末尾有多少個零 N! = K * 10^M N! = 2^X * 3^Y * 5^Z M = min(X,Z) 其中X >= Z,因為能被2整除的數出現的頻率比能被5整除的數高很多。 於是只需計算因式分解中5的指數。 1: ret = 0; for (int i = 1; i <

    併發程式設計,帶你深入理解java多執行緒原理

    1.什麼是多執行緒? 多執行緒是為了使得多個執行緒並行的工作以完成多項任務,以提高系統的效率。執行緒是在同一時間需要完成多項任務的時候被實現的。 2.瞭解多執行緒 瞭解多執行緒之前我們先搞清楚幾個重要的概念! 如上圖所示:對我們的專案有一個主記憶體,這個主記憶體裡面存放了我們的共享變數、方法區、堆中的物件等

    程式設計---電梯排程演算法

    在看linux 0.11版本的塊裝置驅動部分,裡面提到了電梯演算法,總結下幾種尋道的方式。         第一種:最為原始的先到先服務(first come first served)的演算法。假設此時我們正在第11道讀取資料,然後陸陸續續有其他程序來要求我們提供磁碟內容

    程式設計-1.3-烙餅排序問題

    問題描述: 烙餅問題可以簡化為對一段由n個無重複的整陣列成的無序陣列a[n]進行排序。排序要求每次只能對a[0]~a[i]部分的陣列進行翻轉(0 < i < n),最終完成排序。 輸入:陣列大小n;n個整數。 輸出:最小遞迴查詢次數m;每次翻轉位置j

    程式設計-1.4-買書問題

    問題描述: 《哈利波特》1-5卷促銷活動,每本8元。買不同的n本可以對應不同的折扣如下。 求解一筆訂單中,購買不同卷數不同本數的最少價格解。 問題思考: 書中給出了兩種解題思路: 思路一: 參照上一小節,仍使用遞迴方式遍歷所有解,取得最優解。 思路二: 採用貪

    程式設計---網易遊戲-2017實習筆試題

    編碼 題目1: 給定一個字串,請你將字串重新編碼,將連續的字元替換成“連續 出現的個數+字元”。比如字串AAAABCCDAA會被編碼成4A1B2C1D2A。.統計連續出現的字元數目.注意數字字串之間轉換,別要在這些細節上浪費太多時間,要不然後邊題沒時間做!程式碼:#inclu

    程式設計】初賽2015 待填坑

    初賽第一場 題目1 : 彩色的樹 時間限制:2000ms 單點時限:1000ms 記憶體限制:256MB 描述 給定一棵n個節點的樹,節點編號為1, 2, …, n。樹中有n - 1條邊,任意兩個節點間恰好有一條路徑。這是一棵彩色的樹,每個節點恰好可以染一

    程式設計---最長有效括號字串

    題目         給定字串,僅包含左括號‘(’和右括號‘)’,它可能不是括號匹配的,設計演算法,找出最長匹配的括號子串,返回該子串的長度。         如:                  (():2                  ()():4         

    程式設計小飛的電梯排程演算法(多種解法)---Java語言

    1.題目情景         我們假設都是從一樓上電梯的,而至於訊電梯停在其中的某一層。即所有的乘客都從一樓上電梯,到達某層之後,電梯停下來,所有乘客再從這裡爬樓梯到自己的目的層。在一樓的時候,每個乘客選擇自己的目的層,電梯則自動計算出應停的樓層,並且能夠保證該層停使得所有