這幾天在看面試題目,與以前做acm的題目有不同的感覺。從題目題材上說acm由於不同客戶機的系統等有差異,所以一般都會選擇通用性的算法很少涉及本地的API之類的東西,同時acm很少對代碼內容做限制,更多的是要求時間復雜度和空間復雜度。而面試題目是在專用機器上做的,同時沒有標准化的輸入輸出,只要你能跑通即可,但是面試官可以對你的代碼做更多的要求,比如說只用一個變量,不能用庫函數,用某種系統的底層API等。這些使得平時我們的面試與acm有較大的差別,我看了leetcode上面的題目感覺跟面試題目的口味有點像,不過不知道他們是怎麼判正誤的,感覺是個不錯的平台。
下面的做法是把一個char變量(8位)分成上四位和下四位,上四位表示A的位置,下四位表示B的位置,明顯發現這裡的輸出都是用戶自定義的,在面試的時候沒有要求輸出,只需提供合理的一種思路即可。
#include <stdio.h> #define HALF_BITS_LENGTH 4 //這個值是記憶存儲單元長度的一般,在這道題裡是4bit; #define FULLMASK 255 //這個數字表示一個全部bit的mask,在二進制表示中,它是11111111 #define LMASK (FULLMASK<<HALF_BITS_LENGTH) //這個宏表示一個左bit的mask,在二進制表示中,它是11110000、 //用宏的時候如果裡面有運算符,記得加括號 #define RMASK (FULLMASK>>HALF_BITS_LENGTH) //這個宏表示一個左bit的mask,在二進制表示中,它是00001111、 #define RSET(b,n) (b=((LMASK&b)^n)) //這個宏將b的右邊設置成n; #define LSET(b,n) (b=((RMASK&b)^(n<<HALF_BITS_LENGTH))) //這個宏,將b的左邊設置成n; #define RGET(b) (RMASK&b) //這個宏得到b右邊的值; #define LGET(b) ((LMASK&b)>>HALF_BITS_LENGTH) //這個宏得到b左邊的值; #define GRIDW 3 //grid的寬度, //以上的作為給我們封裝數據結構提供了另外一種思路——使用宏定義 //以上的宏定義設置了一個數據結構,這個數據結構的變量為一個BITE, //操作為對左半部分賦值和右半部分賦值,以及分別獲得左右兩部分的值; //這裡用了抽象和分層設計其中RSET LSET RGET LGET GRIDW直接作為應用宏供調用 //LMASK RMASK 為抽象出來的第二層宏,FULLMASK和HASL_BITS_LENGTH 為底層調用。 //這個設計思路肯定是自上向下的,而不是自下向上。 int main() { unsigned char b;//使用unsigned可以獲取一個8位數字; for(LSET(b,1);LGET(b)<=GRIDW*GRIDW;LSET(b,(LGET(b)+1))) for(RSET(b,1);RGET(b)<=GRIDW*GRIDW;RSET(b,(RGET(b)+1))) if(LGET(b)%GRIDW!=RGET(b)%GRIDW) printf("A=%d,B=%d\n",LGET(b),RGET(b)); return 0; }
posA*9+posB取遍(0-80) 並且每對位置與唯一的一個值一一對應,這個是個很重要的思路,把兩個值的關系映射到一個坐標軸上。
C語言中可以使用unsigned char 來表示一個字節的整數,所以char型本質上也是整數類型。看吧,這裡是倒序輸出了數據對 依然沒有什麼大礙。
#include <stdio.h> int main() { unsigned char b = 81; while(b--) { if(b/9%3!=b%9%3) printf("A=%d,B=%d\n",b/9%3+1,b%9%3+1); } return 0; }
這裡使用了結構體共用字節的特點。
#include <stdio.h> int main() { struct{ unsigned char a:4; unsigned char b:4; }i; for(i.a = 1;i.a<=9;i.a++) { for(i.b=1;i.b<=9;i.b++) if(i.a%3 != i.b%3) printf("A = %d,B=%d\n",i.a,i.b); //printf("A:%c%d B:%c%d\n",'d'+i/3,i%3+1); } return 0; }