面试手撕合集

已知高频面试题

一、链表

1.移除链表元素

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummmyhead = new ListNode(0);
        ListNode* cur = dummmyhead;
        dummmyhead->next = head;
        while(cur->next != nullptr){
            if (cur->next->val == val){
                cur->next = cur->next->next;
            }
            else cur = cur->next;
        }
        return dummmyhead->next;
    }
};

 

2.反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr) return head;
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while(cur != nullptr){
            ListNode* tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        
        return pre;
    }
};

 

3.两两交换链表节点

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        ListNode* pre = dummy;
        ListNode* cur = head;
        while(cur != nullptr && cur->next != nullptr){
            ListNode* tmp = cur->next->next;
            cur->next->next = cur;
            pre->next = cur->next;
            cur->next = tmp;
            pre = cur;
            cur = tmp;
        }
        return dummy->next;
    }
};

 

4.删除链表中的倒数第N个节点

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        ListNode* pre = dummy;
        ListNode* cur = head;
        while(n--) cur = cur->next;
        while(cur != nullptr){
            cur = cur->next;
            pre = pre->next;
        }
        pre->next = pre->next->next;
        return dummy->next;
    }
};

 

一、设计模式

1.单例模式

2.观察者模式(信号与槽、智能指针?)

 

 

二、排序算法

1.插入排序


 

 

2.冒泡排序

3.快速排序

4.归并排序

5.堆排序

 

三、查找算法

1.二分查找

 

四、字符串题

1.实现strStr()

2.实现strcpy()

3.实现strcmp()

4.回文字符串

5.划分字符区间

这里用到的技巧是当我感觉需要多次进入某个循环(至少进入一次)但后续进入的条件不明确时,就用while+ flag追加下次进入条件的方式写。

另外vector<int> out(26, 0)这种之类的写法很容易引起歧义所以会报错,用赋值的方法去替换。

 

五、二叉树题

1.翻转二叉树

class Solution {
public:
    void invert(TreeNode* root){
        if(root == nullptr) return;
        swap(root->left, root->right);
        invert(root->left);
        invert(root->right);
    }

    TreeNode* invertTree(TreeNode* root) {
        invert(root);
        return root;
    }
};
View Code

 

 2.对称二叉树

class Solution {
public:
    bool checkSame(TreeNode* left, TreeNode* right){
        if(left == nullptr && right == nullptr) return true;
        if(left == nullptr && right != nullptr) return false;
        if(left != nullptr && right == nullptr) return false;
        bool checkOutSide = checkSame(left->left, right->right);
        bool checkInside = checkSame(left->right, right->left);
        if(checkInside && checkOutSide && left->val == right->val) return true;
        return false;
    }

    bool isSymmetric(TreeNode* root) {
        return checkSame(root->left, root->right);
    }
};
View Code

 

五.深度/广度优先搜索

1.岛屿数量 DFS版本

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

    void color(vector<vector<char>>& grid, int x, int y, vector<vector<int>>& visited){
        visited[x][y] = 1;
        for (int i = 0; i < 4; i++){
            int newx = x + dx[i];
            int newy = y + dy[i];
            if (newx >= 0 && newy >= 0 && newx < grid.size() && newy < grid[0].size() && grid[newx][newy] == '1' && visited[newx][newy] == 0){
                color(grid, newx, newy, visited);
            }
        }
    }

    int numIslands(vector<vector<char>>& grid) {
        int count = 0;
        vector<vector<int>> visited(grid.size(), vector<int>(grid[0].size(), 0));
        for(int i = 0; i < grid.size(); i++){
            for(int j = 0; j < grid[0].size(); j++){
                if (grid[i][j] == '1' && visited[i][j] == 0){
                    count++;
                    color(grid, i, j, visited);
                }
            }
        }
        return count;
    }
};

 

2. 岛屿数量 BFS版本

class Solution {
public:
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};
    vector<vector<int>> path;
    void bfs(vector<vector<char>>& grid, vector<vector<int>>& visited){
        //cout << "path" << path.size() << endl;
        while(!path.empty()){
            vector<int> incor = path.back();
            path.pop_back();
            int x = incor[0];
            int y = incor[1];
            cout << x << y << endl;
            for (int i = 0; i < 4; i++){
                int newx = x + dx[i];
                int newy = y + dy[i];
                if (newx < 0 || newx >= grid.size() || newy < 0 || newy >= grid[0].size()) continue;

                if (grid[newx][newy] == '1' && visited[newx][newy] == 0){
                    path.push_back({newx, newy});
                    visited[newx][newy] = 1;
                }
            }
        }

        
    }

    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        vector<vector<int>> visited(n, vector<int>(m, 0));
        //cout <<"enter" << endl;
        int count = 0;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if (grid[i][j] == '1' && visited[i][j] == 0){
                    //cout <<"enter" << endl;
                    count++;
                    visited[i][j] = 1;
                    path.push_back({i, j});
                    bfs(grid, visited);
                }
            }
        }
        return count;

    }
};

3.岛屿最大面积(BFS)

class Solution {
public:
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};
    vector<vector<int>> path;
    int bfs(vector<vector<int>>& grid, vector<vector<int>>& visited){
        int n = grid.size();
        int m = grid[0].size();
        int count = 1;
        while(!path.empty()){
            vector<int> cor = path.back();
            path.pop_back();
            int x = cor[0];
            int y = cor[1];
            for(int i = 0; i < 4; i++){
                int newx = x + dx[i];
                int newy = y + dy[i];
                if (newx < 0 || newx >= n || newy < 0 || newy >= m) continue;
                if (grid[newx][newy] == 1 && visited[newx][newy] == 0){
                    visited[newx][newy] = 1;
                    count++;
                    path.push_back({newx, newy});
                }
            }
        }


        return count;
    }


    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        int curCount;
        int historyMax = 0;
        vector<vector<int>> visited(n, vector<int>(m, 0));
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(grid[i][j] == 1 && visited[i][j] == 0){
                    visited[i][j] = 1;
                    path.push_back({i, j});
                    curCount = bfs(grid, visited);
                    historyMax = max(curCount, historyMax);
                }
            }
        }
        return historyMax;
    }
};

 

 

贪心算法

1.加油站(力扣134)

自己写法超时,附上自己的代码,每次判断剩余油量,不够就切到下一个,结果会超时。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        vector<int> red(gas);
        for(int i = 0; i < red.size(); i++){
            red[i] = gas[i] - cost[i];
        }
        int st = -1;
        bool flag = true;
        //如果某一刻sum 小于0说明不足以到达下个点,则从本次起点的下一个点开始作为起点。
        //如何统计跨边界的sum
        int size = red.size();
        while(flag && st < size - 1){
            flag = false;
            st = (st + 1) % red.size();
            int loc = st;
            int sum = 0;
            while(loc <= red.size() - 1){
                sum += red[loc];
                loc++;
                if(sum < 0){
                    flag = true;
                    break;
                }
            }
            if(flag) continue;
            loc = 0;
            while(loc < st){
                sum += red[loc];
                loc++;
                if(sum < 0){
                    flag = true;
                    break;
                }
            }
            if(flag) continue;
            return st;
        }
        return -1;
    }
};
View Code

 代码随想录的答案的核心思想:tarSum表明如果无所谓过程中sum小不小于0,首先如果最后都是小于0的,一定跑不完一圈

但问题是最后大于0,起点未必是能从0开始的,可能0是最后一个点也说不好,所以提出一个过程中去统计的curSum,如果curSum小于0了,那么起点从i的下一个开始。

 

738.单调递增的数字 (直接搜力扣不要自己写)

posted @ 2023-09-10 18:48  timeMachine331  阅读(34)  评论(0)    收藏  举报