在看《程序员面试金典》,里面150题有一些不错的,提交地址 ,记录整理一下:
5.3最接近的数
有一个正整数,请找出其二进制表示中1的个数相同、且大小最接近的那两个数。(一个略大,一个略小)
略大的数,考虑把数字最末端的那个0变成1,之后把剩下的1都堆到最左边,当然这需要过滤0(从左到右),再找1,再找0,把这个0变为1。
略小的数,考虑把数字最末端的那个1变成0,之后把剩下的1都堆到最右边,先过滤1,再找0,再找1,把这个1变为0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class CloseNumber { public : int find_min (int x) { int res = x; int p = 0 ; int cnt1 = 0 , cnt0 = 0 ; while ((1 << p)&res) { res ^= (1 << p); p++; cnt1++; } cnt0++; p++; while (((1 << p)&res) == 0 ) { p++; cnt0++; } cnt1++; res ^= (1 << p); res ^= ((1 << cnt1) - 1 ) << (cnt0 - 1 ); return res; } int find_max (int x) { int res = x; int p = 0 ; int cnt1 = 0 , cnt0 = 0 ; while (((1 << p)&res)==0 ) { p++; cnt0++; } res ^= (1 << p); p++; while (((1 << p)&res)) { res ^= (1 << p); p++; cnt1++; } res ^= (1 << p); cnt0++; res ^= ((1 << cnt1) - 1 ); return res; } vector<int > getCloseNumber (int x) { vector<int >ans; ans.push_back (find_min (x)); ans.push_back (find_max (x)); return ans; } }wc;
5.7像素设定
有一个单色屏幕储存在一维数组中,其中数组的每个元素代表连续的8位的像素的值,请实现一个函数,将第x到第y个像素涂上颜色(像素标号从零开始),并尝试尽量使用最快的办法。
给定表示屏幕的数组screen(数组中的每个元素代表连续的8个像素,且从左至右的像素分别对应元素的二进制的从低到高位),以及int x,int y,意义如题意所述,保证输入数据合法。请返回涂色后的新的屏幕数组。
写起来陷阱还是挺多,挺麻烦的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Render { public : vector<int > renderPixel (vector<int > screen, int x, int y) { int rx = x / 8 , cx = x % 8 ; int ry = y / 8 , cy = y % 8 ; if (rx < ry) { for (int k = rx + 1 ; k < ry; k++) { screen[k] = 0xff ; } int num = 8 - cx; screen[rx] |= (((1 << (num)) - 1 ) << cx); screen[ry] |= ((1 << (cy + 1 )) - 1 ); } else { screen[rx] |= 0xff & ~((1 << cx) - 1 )&((1 << (cy + 1 )) - 1 ); } return screen; } };
9.3魔术索引(1)
在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个升序数组,元素值各不相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。
给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。
如果元素各不相同,通过A[mid]与mid之间的比较,可以直接二分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class MagicIndex {public : bool findMagicIndex (vector<int > A, int n) { int sz = A.size (); int le = 0 , ri = sz - 1 ; while (le < ri) { int mid = (le + ri) >> 1 ; if (A[mid] == mid) { return true ; } else if (A[mid] > mid) { ri = mid - 1 ; } else { le = mid + 1 ; } } return A[le]==le; } };
魔术索引(2)
在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个不下降序列,元素值可能相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。
给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。
元素如果可能重复的话,那么二分就不能判定了,每次递归搜索左半部分和右半部分,可以跳过一些元素。具体情况看代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class MagicIndex {public : bool findMagicIndex (vector<int > A, int n) { return find (A, 0 , n, n); } bool find (vector<int >&A, int st, int en, int n) { if (st > en || st<0 || en>n)return false ; int mid = (st + en) >> 1 ; if (A[mid] == mid)return true ; int le = min (mid - 1 , A[mid]); int ri = max (mid + 1 , A[mid]); return find (A, st, le, n) || find (A, ri, en, n); } }wc;
9.10推箱子
有一堆箱子,每个箱子宽为wi,长为di,高为hi,现在需要将箱子都堆起来,而且为了使堆起来的箱子不到,上面的箱子的宽度和长度必须小于下面的箱子。请实现一个方法,求出能堆出的最高的高度,这里的高度即堆起来的所有箱子的高度之和。
给定三个int数组w,l,h,分别表示每个箱子宽、长和高,同时给定箱子的数目n。请返回能堆成的最高的高度。保证n小于等于500。
和最长递增数列一个动态规划的思路,前面来一个冒泡排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Box { public : int getHeight (vector<int > w, vector<int > l, vector<int > h, int n) { for (int i = 0 ; i < w.size (); i++) { for (int j = 0 ; j < w.size () - i - 1 ; j++) { if (w[j] > w[j + 1 ]) { swap (w[j], w[j + 1 ]); swap (l[j], l[j + 1 ]); swap (h[j], h[j + 1 ]); } } } for (int i = 0 ; i < w.size (); i++) { cout << w[i] << " " << l[i] << " " << h[i] << endl; } vector<int >res (w.size (), 0 ); for (int i = w.size ()-1 ; i >= 0 ; i--) { int ans = 0 ; for (int j = w.size ()-1 ; j > i; j--) { if (w[i] < w[j] && l[i] < l[j]) { ans = max (ans, res[j]); } } res[i] = ans + h[i]; } int ans = 0 ; for (auto it : res) { ans = max (ans, it); } return ans; } };