leetcode-cn 剑指offer

记录下力扣上的剑指题。目前是第一遍,看了题解的前面标*

面试题06 从尾到头打印链表

解法一:利用stack的LIFO性质。时间31.14% 空间100.00%

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        if(!head) return vector<int>{};
        stack<int> st;
        while(head) {
            st.push(head->val);
            head = head->next;
        }
        vector<int> ret;
        while(!st.empty()) {
            ret.push_back(st.top());
            st.pop();
        }
        return ret;
    }
};

解法二:递归 时间66.86%,空间100%

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        if(!head) return vector<int>{};
       
        vector<int> ret = reversePrint(head->next);
        ret.push_back(head->val);
        return ret;
    }
};

面试题07 重建二叉树

解法一:递归.效率很低,时间5%需要优化

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        //前序确定根,切分后递归
        if(preorder.empty())
            return nullptr;
        int root_val = preorder[0];
        int i = 0;
        while(inorder[i] != root_val) ++i;
        vector<int> in1, in2, pre1, pre2;
        copy(inorder.begin(), inorder.begin() + i, back_inserter(in1));
        copy(inorder.begin() + i + 1, inorder.end(), back_inserter(in2));
        copy(preorder.begin() + 1, preorder.begin() + 1 + in1.size(), back_inserter(pre1));
        copy(preorder.begin() + 1 + in1.size(), preorder.end(), back_inserter(pre2));
        TreeNode* root = new TreeNode(root_val);
        root->left = buildTree(pre1, in1);
        root->right = buildTree(pre2, in2);
        return root;
    }
};

面试题09 用两个栈实现队列

class CQueue {
private:
    stack<int> s1;
    stack<int> s2;
public:
    CQueue() {

    }
    
    void appendTail(int value) {
        s1.push(value);
    }
    
    int deleteHead() {
        int ret = -1;
        if(!s2.empty()) {
            ret = s2.top();s2.pop();
        } else if(!s1.empty()) {
            while(!s1.empty()) {
                s2.push(s1.top());
                s1.pop();
            }
            ret = s2.top();s2.pop();
        }

        return ret;
    }
};

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue* obj = new CQueue();
 * obj->appendTail(value);
 * int param_2 = obj->deleteHead();
 */

面试题10- I 斐波那契数列

class Solution {
public:
    int fib(int n) {
        int dp[101];
        dp[0] = 0;dp[1] = 1;
        for(int i = 2; i<=n; ++i) {
            dp[i] = (dp[i-1] + dp[i-2])%1000000007;
        }
        return dp[n];
    }
};

面试题11 旋转数组的最小数字

class Solution {
public:
    int minArray(vector<int>& numbers) {
        int len = numbers.size();
        int lo = 0, hi = len - 1, mid = 0;
        
        while(lo < hi) {
            mid = (lo + hi) >> 1;
            if(numbers[mid] < numbers[hi])
                hi = mid;
            else if(numbers[mid] > numbers[hi])
                lo = mid + 1;
            else if(numbers[mid] == numbers[hi])
                hi = hi - 1;
        }
        return numbers[lo];
    }
};

面试题12. 矩阵中的路径

dfs遍历回溯

class Solution {
private:
    int dx[4] = {0, 0, -1, 1};
    int dy[4] = {-1, 1, 0, 0};
    int rowlen;
    int collen;
    bool visited[201][201];

    bool dfs(vector<vector<char>>& board, string word, int row, int col, int idx) {
        
        if(row<0 || row >= rowlen || col<0 || col>=collen || board[row][col] != word[idx]) return false;
        if( visited[row][col])  return false;
        visited[row][col] = true;
        if(idx == word.size() - 1) return true;
        bool ret=false;
        for(int k = 0; k < 4; ++k) {
            int rx = row + dx[k];
            int ry = col + dy[k];
            if(dfs(board, word, rx, ry, idx + 1))
                {ret=true;break;}
        }
        if(!ret) visited[row][col]=false;  // 记得回溯
        return ret;
    }

public:
    bool exist(vector<vector<char>>& board, string word) {
        rowlen = board.size();
        collen = board[0].size();
        for(int i=0; i < rowlen; ++i)
            for(int j=0; j < collen; ++j) {
                memset(visited, false, sizeof(visited));
                if(dfs(board, word, i, j, 0)) return true;
            }
        return false;
    }
};

visited数组可以优化掉

class Solution {
private:
    int dx[4] = {0, 0, -1, 1};
    int dy[4] = {-1, 1, 0, 0};
    int rowlen;
    int collen;

    bool dfs(vector<vector<char>>& board, string word, int row, int col, int idx) {
        
        if(row<0 || row >= rowlen || col<0 || col>=collen || board[row][col] != word[idx]) return false;
        if(idx == word.size() - 1) return true;
        
        char tmp = board[row][col];
        board[row][col] = '/';
        bool ret=false;
        for(int k = 0; k < 4; ++k) {
            int rx = row + dx[k];
            int ry = col + dy[k];
            if(dfs(board, word, rx, ry, idx + 1))
                {ret=true;break;}
        }
        board[row][col] = tmp;
        return ret;
    }

public:
    bool exist(vector<vector<char>>& board, string word) {
        rowlen = board.size();
        collen = board[0].size();
        for(int i=0; i < rowlen; ++i)
            for(int j=0; j < collen; ++j) {
                if(dfs(board, word, i, j, 0)) return true;
            }
        return false;
    }
};

面试题52. 两个链表的第一个公共节点

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* h1,*h2;
        h1 = headA; h2 = headB;
        while(h1 != NULL) {
            for(h2 = headB; h2 != NULL; h2 = h2->next) {
                if(h1 == h2) return h1;
            }
            h1 = h1->next;
        }
        return NULL;
    }
};

死方法,效率低。可以用快慢指针

面试题53 - I. 在排序数组中查找数字 I

class Solution {
public:
    int search(vector<int>& nums, int target) {
        unordered_map<int, int> hash;
        for(auto c: nums)
            ++hash[c];
        return hash[target];
    }
};

哈希效率挺低的,注意是排好序的,想到二分法。求左右边界即可


posted @ 2020-04-12 14:42  pusidun  阅读(175)  评论(0编辑  收藏  举报