楼主: 大木虫
跳转到指定楼层
上一主题 下一主题
收起左侧

Elements of Programming Interviews 白班编程记录,求挑刺求反馈

 
🔗
 楼主| 大木虫 2018-11-1 03:33:32 | 只看该作者
全局:
LC 73. Set Matrix Zeroes
我这道题用的是bit mask,但是bit mask的问题是会出现overflow。
看了LC答案,答案的思路是把O(M+N)的方法变成in-place,之所以可以这样做是因为这样正好巧妙地绕过了cell-influence-other-cell的题目trick。不错。
take away:比较累的时候会出现比较多的差错,这点还需要训练,以及要放慢速度,耐心写题。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        for(int i = 0; i < matrix.size(); ++i){
            for(int j = 0; j < matrix[0].size(); ++j){
                if(matrix[i][j] > 0){
                    matrix[i][j] *= 2;
                    matrix[i][j] += 1;                    
                }
            }
        }
        
        for(int i = 0; i < matrix.size(); ++i){
            for(int j = 0; j < matrix[0].size(); ++j){
                if(matrix[i][j] == 0){
                    SetRowTwo(&matrix, i);
                    break;
                }
            }
        }
        
        for(int j = 0; j < matrix[0].size(); ++j){
            for(int i = 0; i < matrix.size(); ++i){
                if(matrix[i][j] == 0){
                    SetColTwo(&matrix, j);
                    break;
                }
            }
        }
        
        for(int i = 0; i < matrix.size(); ++i){
            for(int j = 0; j < matrix[0].size(); ++j){
                if(matrix[i][j] == 2)matrix[i][j] = 0;
                else matrix[i][j] = (matrix[i][j]-1)/2;
            }
        }
    }
   
    void SetRowTwo(vector<vector<int> > * matrix, int i){
        for(int j = 0; j < (*matrix)[i].size(); ++j){
            if((*matrix)[i][j] == 0)continue;
            (*matrix)[i][j] = 2;
        }
    }
   
    void SetColTwo(vector<vector<int> > * matrix, int j){
        for(int i = 0; i < matrix->size(); ++i){
            if((*matrix)[i][j] == 0)continue;
            (*matrix)[i][j] = 2;
        }
    }
};

补充内容 (2018-11-1 03:34):
【i】又被网页省掉了。。。
这里的matrix[j] 其实都是matrix【i】【j】
回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-1 03:47:30 | 只看该作者
全局:
LC 64. Minimum Path Sum
这道题没有上白板,直接在OJ写的,典型DP,7分钟bug free完成

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        /* 0. MISC */
        if(grid.size() == 0 || grid[0].size() == 0)return 0;
        
        /* 1. prep */
        vector<int> costRow;
        
        int cost = 0;
        for(int num : grid[0]){
            cost += num;
            costRow.emplace_back(cost);
        }
        
        /* 2. key algo */
        for(int i = 1; i < grid.size(); ++i){
            vector<int> newRow = {grid[i][0] + costRow[0]};
            for(int j = 1; j < grid[0].size(); ++j){
                newRow.emplace_back(min(costRow[j], newRow[j-1]) + grid[i][j]);
            }
            costRow = move(newRow);
        }
        
        /* 3. answer */
        return costRow.back();
    }
};

补充内容 (2018-11-1 03:48):
take away:写的速度控制在想的速度之下,稍微慢一点,让思考领着手写,下手前,思路先过一遍可能的坑以及未来几步,这样写出的代码错误少。这点tips可以用于比较累的情况和general情况。
回复

使用道具 举报

全局:
lz 你可以在 高级模式里面找到 这个图标 “ <> ”

然后贴代码

  1. // comment
复制代码


回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-1 22:47:22 | 只看该作者
全局:
爱丽丝和鲍勃 发表于 2018-11-1 03:51
lz 你可以在 高级模式里面找到 这个图标 “  ”

然后贴代码

我知道有那个选项,可是那样没法高亮错误行
回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-1 22:51:58 | 只看该作者
全局:
LC 272. Closest Binary Search Tree Value II
旧题重新练习,50分钟,白板110行代码,难度还是比较大的。

take away: pointer syntax consistency是个很容易出问题的地方,解决办法是全部写完之后统一检查。
take away:continue不能在loop外使用
改使用代码显示,唯一问题是没法高亮出错的地方,所以使用comment标注出错的地方。
  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. *     int val;
  5. *     TreeNode *left;
  6. *     TreeNode *right;
  7. *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. class Solution {
  11. public:
  12.     vector<int> closestKValues(TreeNode* root, double target, int k) {
  13.         /* 0. MISC */
  14.         if(k < 1)return {};
  15.         
  16.         /* 1. prep */
  17.         stack<TreeNode*> path;
  18.         vector<int> answer;
  19.         
  20.         /* 2. key algo */
  21.         /* find closest */
  22.         FindClosest(root, target, &path);
  23.         stack<TreeNode*> prevPath(path), nextPath(path);
  24.         answer.emplace_back(path.top()->val);
  25.         
  26.         /* get k - 1 additional closest nodes */
  27.         Next(&nextPath); Prev(&prevPath);
  28.         while(--k > 0){
  29.             if(nextPath.empty()){
  30.                 answer.emplace_back(prevPath.top()->val);
  31.                 Prev(&prevPath);
  32.             }else if(prevPath.empty()){
  33.                 answer.emplace_back(nextPath.top()->val);
  34.                 Next(&nextPath);
  35.             }else{
  36.                 int nextVal = nextPath.top()->val;
  37.                 int prevVal = prevPath.top()->val;
  38.                 if(nextVal-target < target - prevVal){
  39.                     answer.emplace_back(nextVal);
  40.                     Next(&nextPath);
  41.                 }else{
  42.                     answer.emplace_back(prevVal);
  43.                     Prev(&prevPath);
  44.                 }
  45.             }
  46.         }
  47.         
  48.         /* 3. answer */
  49.         return answer;
  50.     }
  51.    
  52.     void Next(stack<TreeNode*> * path){
  53.         TreeNode* current = path->top();
  54.         if(current->right){
  55.             current = current->right;
  56.             path->emplace(current);
  57.             while(current->left){
  58.                 current = current->left;
  59.                 path->emplace(current);
  60.             }
  61.         }else{
  62.             path->pop();
  63.             while(!path->empty() && path->top()->right == current){
  64.                 current = path->top();
  65.                 path->pop();
  66.             }
  67.         }
  68.     }
  69.    
  70.     void Prev(stack<TreeNode*> * path){
  71.         TreeNode* current = path->top();
  72.         if(current->left){
  73.             current = current->left;
  74.             path->emplace(current);
  75.             while(current->right){
  76.                 current = current->right;
  77.                 path->emplace(current);
  78.             }
  79.         }else{
  80.             path->pop();
  81.             while(!path->empty() && path->top()->left == current){
  82.                 current = path->top();
  83.                 path->pop();
  84.             }
  85.         }
  86.     }
  87.    
  88.     void FindClosest(TreeNode * root, double target, stack<TreeNode*> * path){
  89.         /* 0. MISC */
  90.         if(!root)return;
  91.         
  92.         /* 1. prep */
  93.         while(!path->empty())path->pop();
  94.         TreeNode* current = root;
  95.         
  96.         /* 2. key algo */
  97.         while(current){
  98.             path->emplace(current);
  99.             if(current->val > target){
  100.                 current = current->left;
  101.             }else if(current->val < target){
  102.                 current = current->right;
  103.             }else current = NULL;           
  104.         }
  105.         int val = path->top()->val;
  106.         stack<TreeNode*> copyPath(*path);
  107.             
  108.         if(val > target){
  109.             Prev(&copyPath);
  110.             /* problem line here */
  111.             if(!copyPath.empty() && target - copyPath.top()->val < val - target){
  112.                 *path = move(copyPath);
  113.             }
  114.         }else if(val < target){
  115.             Next(&copyPath);
  116.             /* problem line here */
  117.             if(!copyPath.empty() && copyPath.top()->val - target < target - val){
  118.                 *path = move(copyPath);
  119.             }
  120.         }
  121.     }
  122. };
复制代码
回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-1 23:54:33 | 只看该作者
全局:
LC 124. Binary Tree Maximum Path Sum
take away: 看清题目要求(a valid path should contain at least one node)
take away: 对于recursion,代码通常比较短,但是逻辑稍微复杂,所以要先想清楚,在写,不要担心写得慢,因为想清楚的recursion正确代码不需要多少时间就可以写完。

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. *     int val;
  5. *     TreeNode *left;
  6. *     TreeNode *right;
  7. *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. class Solution {
  11. public:
  12.     int maxPathSum(TreeNode* root) {
  13.         /* 0. MISC */
  14.         if(!root) return 0;
  15.         
  16.         /* 1. prep */
  17.         int answer = 0, maxNode = INT_MIN;
  18.         
  19.         /* 2. key algo */
  20.         MaxPathSumRec(root, &answer, &maxNode);
  21.         
  22.         /* 3. answer */
  23.         if(maxNode < 0){
  24.             return maxNode;
  25.         }else return answer;
  26.     }
  27.    
  28.     int MaxPathSumRec(TreeNode* node, int* curMax, int* maxNode){
  29.         /* base case */
  30.         if(!node)return 0;
  31.         
  32.         /* pre-order */
  33.         *maxNode = max(*maxNode, node->val);
  34.         
  35.         /* recursion */
  36.         int leftVal = MaxPathSumRec(node->left, curMax, maxNode);
  37.         int rightVal = MaxPathSumRec(node->right, curMax, maxNode);
  38.         
  39.         /* post-order */
  40.         *curMax = max(*curMax, node->val + leftVal + rightVal);
  41.         return max(max(node->val, 0), node->val + max(leftVal, rightVal));
  42.         
  43.     }
  44.    
  45. };
复制代码
回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-2 03:12:24 | 只看该作者
全局:
LC 636. Exclusive Time of Functions
新题,37分钟写码 + 8分钟example

take away: struct init need forward declaraction
take away: 写之前把问题彻底搞清楚,这样避免进入误区浪费思考时间
take away: 写每一步前彻底想清楚,然后一遍写对
take away: 看这到题是在模拟什么情景,然后用该情景的惯常做法解决,举例,本题模仿的情景是function call stack,那我们就用stack解决它
take away: 像这种simulation题目用画图来解释例子特别的直观方便。

  1. class Solution {
  2. public:
  3.     struct Log{
  4.         int id, stamp;
  5.         string op;
  6.         Log(string op_, int stamp_, int id_):
  7.             op(op_), stamp(stamp_), id(id_){}
  8.     };
  9.    
  10.     vector<int> exclusiveTime(int n, const vector<string>& logs) {
  11.         /* 0. MISC */
  12.         
  13.         /* 1. prep */
  14.         stack<int> callStack;
  15.         int prevStamp = 0;
  16.         string prevOp;
  17.         vector<int> answer(n, 0);
  18.         
  19.         /* 2. key algo */
  20.         for(string logStr : logs){
  21.             Log log = ParseLog(logStr);
  22.             
  23.             int id = log.id, stamp = log.stamp;
  24.             string op = log.op;
  25.             
  26.             if(op == "start"){
  27.                 if(!callStack.empty()){
  28.                     answer[callStack.top()] += stamp - prevStamp;
  29.                     if(prevOp == "end")answer[callStack.top()]--;
  30.                 }
  31.                 callStack.emplace(id);
  32.             }else{
  33.                 answer[id] += stamp - prevStamp;
  34.                 if(prevOp == "start")answer[id]++;
  35.                 callStack.pop();
  36.             }
  37.             prevStamp = stamp;
  38.             prevOp = op;
  39.         }
  40.         
  41.         /* 3. answer */
  42.         return answer;
  43.     }
  44.    
  45.    
  46.     Log ParseLog(const string & s){
  47.         int firstSep = s.find(":");
  48.         int secondSep = s.find(":", firstSep + 1);
  49.         string idStr = s.substr(0, firstSep);
  50.         string op = s.substr(firstSep + 1, secondSep - firstSep - 1);
  51.         string stampStr = s.substr(secondSep + 1, s.size() - secondSep);
  52.         return Log(op, stoi(stampStr), stoi(idStr));
  53.     }
  54.    

  55. };
复制代码

补充内容 (2018-11-2 03:14):
这是白板代码,直接原文从白板上打下来的,有三个syntax typo,修改后AC
回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-2 03:13:17 | 只看该作者
全局:
大木虫 发表于 2018-11-2 03:12
LC 636. Exclusive Time of Functions
新题,37分钟写码 + 8分钟example

take away: 如果让自定义API,那么怎么舒服方便怎么来,比如说这里的(struct Log)
回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-2 04:12:07 | 只看该作者
全局:
LC 23. Merge k Sorted Lists
take away: 自定义Comparator (functor)的时候要弄清楚正反(greater对应minHeap)

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. *     int val;
  5. *     ListNode *next;
  6. *     ListNode(int x) : val(x), next(NULL) {}
  7. * };
  8. */
  9. class Solution {
  10. public:
  11.     struct Compare{
  12.         bool operator()(ListNode * l1, ListNode * l2){
  13.             if(!l1 || !l2)return false;
  14.             return l1->val > l2->val;
  15.         }
  16.     };
  17.    
  18.     ListNode* mergeKLists(vector<ListNode*>& lists) {
  19.         /* 0. MISC */
  20.         if(lists.empty())return NULL;
  21.         
  22.         /* 1. prep */
  23.         priority_queue<ListNode*, vector<ListNode*>, Compare> listHeap;
  24.         for(auto node : lists){
  25.             if(node)listHeap.emplace(node);
  26.         }
  27.         ListNode* dummyHead = new ListNode(0);
  28.         ListNode* current = dummyHead;
  29.         
  30.         /* 2. key algo */
  31.         while(!listHeap.empty()){
  32.             ListNode* node = listHeap.top();
  33.             listHeap.pop();
  34.             current->next = node;
  35.             current = node;
  36.             if(node->next){
  37.                 listHeap.emplace(node->next);
  38.             }
  39.         }
  40.         
  41.         ListNode* head = dummyHead->next;
  42.         delete dummyHead;
  43.         
  44.         /* 3. answer */
  45.         return head;
  46.     }
  47. };
复制代码

补充内容 (2018-11-2 04:12):
用时15分钟(毕竟典型题目)
回复

使用道具 举报

🔗
 楼主| 大木虫 2018-11-2 22:41:35 | 只看该作者
全局:
LC 301. Remove Invalid Parentheses
这是一道综合题,我第一遍写的时候写了230行
如今上白板,在假设API的前提下实现了主体,43分钟完成,时间还是相对较长的。

take away: 题目细节复杂的时候先自定义几个方便的API,然后先实现主体思路,可以大大提升白板写码的效率

白板代码如下:(右边是几个自定义API):



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表