leetcode_OJ WC67 解題心得
- Contest time: Jan 14, 2018
- Virtual Contest time: Mar 24, 2018
PA. 762. Prime Number of Set Bits in Binary Representation 位元操作水題
- 思路:位元運算抓一,看看一的個數是否為質數
class Solution { public: int bitcnt(int num) { int cnt = 0; while(num > 0) { if(num & 0x1) { cnt++; } num>>=1; } return cnt; } bool is_prime(int num) { if(num == 1) return false; for(int i=2;i<=(int)sqrt(num);i++) { if(num % i == 0) { return false; } } return true; } int countPrimeSetBits(int left, int right) { int cnt = 0, bit = 0; for (size_t i = left; i <= right; i++) { bit = bitcnt(i); if(is_prime(bit)) { cnt++; } } return cnt; } };
PB. 763. Partition Labels 貪心演算法推理題
- 思路:必須讓所有char開始結束均屬於同一個區塊,故利用struct紀錄每一個char的最早開始位置,與最晚結束位置。若字元x的開始位置x_start介於當前最小開始(min_start)與結束(max_end)之間,並且字元x的結束位置大於當前的max_end 則必須再將max_end延伸,否則無法符合題目需求讓char最小開始與最大結束街位在同一個區塊。 每次都找當前最遠的並檢查是否更新(區域最優解),是屬於貪心算法的一種
class Solution { public: struct stend { char alpha; int start, end; }; bool mycompare(stend s1, stend s2) { return s1.start < s2.start; } vector<int> partitionLabels(string str) { int count = str.size(); vector<stend> vec; vec.resize(26); for(int i = 0; i < 26; i++) { vec[i].start = -1; vec[i].end = 0; vec[i].alpha = 0; } vec[str[0]-'a'].start = 0; for (size_t i = 1; i < count; i++) { vec[str[i]-'a'].alpha = str[i]; if(vec[str[i]-'a'].start == -1) { vec[str[i]-'a'].start = i; } if(i > vec[str[i]-'a'].end) { vec[str[i]-'a'].end = i; } } int min_start = vec[str[0]-'a'].start; int max_end = vec[str[0]-'a'].end; //greedy approach int partition = 0; vector<int>res; for (size_t i = 0; i < count; i++) { if( vec[str[i]-'a'].start > min_start && vec[str[i]-'a'].start < max_end && vec[str[i]-'a'].end > max_end ) { max_end = vec[str[i]-'a'].end; } if(i == max_end || i == count - 1)//last will definitely cut over to match. just in case { if(i != count - 1) { res.push_back(max_end - min_start + 1); min_start = vec[str[i + 1]-'a'].start; max_end = vec[str[i + 1]-'a'].end; } else { res.push_back(max_end - min_start + 1); // a special case } } } return res; } };
PC. 764. Largest Plus Sign 動態規劃
- 由於每一點的+號中心,周圍的四角都必須等長為連續的1(重疊子問題),若不等長則只能盡量延伸至『四角最短的角』作為本次的order(最優子結構),因此採用動態規劃
首先把四個方向(朝上 朝下 朝左 朝右 連續的1給記載 例如朝右行進 0110111 → 0120123
朝左行進→ 0210321 的寫法),最後全部走訪過一遍後,對於每一點取min(u,d,l,r)連續一的個數就是當前能組成+號的order(度數)
最後重新走訪一遍找出對於每一點最大的order。
class Solution { public: int orderOfLargestPlusSign(int MAXN, vector<vector<int>>& mines) { int order = 0, count = mines.size(); vector<vector<int>>dp_up(MAXN, vector<int>(MAXN, 1)), dp_down(MAXN, vector<int>(MAXN, 1)), dp_left(MAXN, vector<int>(MAXN, 1)), dp_right(MAXN, vector<int>(MAXN, 1)), dp_ans(MAXN, vector<int>(MAXN, 0)); for (size_t i = 0; i < count; i++) { dp_up[mines[i][0]][mines[i][1]] = 0; dp_down[mines[i][0]][mines[i][1]] = 0; dp_left[mines[i][0]][mines[i][1]] = 0; dp_right[mines[i][0]][mines[i][1]] = 0; } //main dynamic programming //up continuous (bottom up) for(int i = 0;i < MAXN; i++) { for(int j = MAXN - 2;j >= 0; j--) { if(dp_up[j][i] == 1) { dp_up[j][i] = dp_up[j + 1][i] + 1; } } } //down continuous (top down) for(int i = 0;i < MAXN; i++) { for(int j = 1;j < MAXN; j++) { if(dp_down[j][i] == 1) { dp_down[j][i] = dp_down[j - 1][i] + 1; } } } //left continuous for(int i = 0;i < MAXN; i++) { for(int j = MAXN - 2;j >=0 ;j--) { if(dp_left[i][j] == 1) { dp_left[i][j] = dp_left[i][j + 1] + 1; } } } //right continuous for(int i = 0;i < MAXN; i++) { for(int j = 1;j < MAXN; j++) { if(dp_right[i][j] == 1) { dp_right[i][j] = dp_right[i][j - 1] + 1; } } } //check for direction since the plus sign has to satisfiy all the four direction, if one of the direction fails. it has to decrease to that direction for(int i = 0; i < MAXN; i++) { for(int j = 0; j < MAXN; j++) { dp_ans[i][j] = min(min(dp_up[i][j], dp_down[i][j]), min(dp_left[i][j], dp_right[i][j])); if(dp_ans[i][j] > order) { order = dp_ans[i][j]; } } } return order; } };