面试准备算法

找出数组的最大公约数

cpp 复制代码
class Solution {
public:
    int findGCD(vector<int>& nums) {
        int min_num = *min_element(nums.begin(), nums.end());
        int max_num = *max_element(nums.begin(), nums.end());

        return gcd(min_num, max_num);
    }
};
cpp 复制代码
//gcd()函数的用法是包含头文件#include <numeric>
int gcd(int a, int b){
	return b == 0 ? a : gcd(b, a%b);
}

在链表中插入最大公约数

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    int gcd(int a,int b){
        return b == 0 ? a : gcd(b, a%b);
    }
    ListNode* insertGreatestCommonDivisors(ListNode* head) {
        if(head == nullptr || head->next == nullptr){
            return head;
        }
        ListNode*p1 = head;
        ListNode*p2 = head->next;
        while(p2){
            int val = gcd(p1->val, p2->val);
            ListNode* newNode = new ListNode(val, p2);
            p1->next = newNode;

            p1 = p2;
            p2 = p2->next;
        }
        return head;
    }
};

使子数组最大公约数大于一的最小分割数



贪心+数学

对于数组中的每个元素,如果它与前面的元素最大公约数为1,那么它需要作为新的子数组的第一个元素。否则,它可以与前面的元素放在同一个子数组中。

因此,我们先初始化一个变量g,表示当前子数组的最大公约数。初始时,g为0,答案变量ans=1。

从前向后遍历数组,维护当前子数组的最大公约数g。如果当前元素x与g的最大公约数为1,那么我们需要将当前元素作为一个新的子数组的第一个元素。

cpp 复制代码
class Solution{
public:
	int minimumSplits(vector<int>& nums){
		int ans = 1, g = 0;
		for(int num: nums){
			g = gcd(g, num);
			if(g == 1){
				++ans;
				g = num;
			}
		}
		return ans;
	}
};

求最大公约数通用公式

cpp 复制代码
int gcd(int a, int b){
	return b == 0 ? a : gcd(b, a%b); 
}

查看Linux磁盘用量常用命令

df -h

du -h

最长连续序列

cpp 复制代码
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int ret = 0;
        unordered_set<int> num_set;
        for(int num : nums){
            num_set.insert(num);
        }

        for(int num : nums){
            //前一个没有
            if(!num_set.count(num-1)){
                int currentNum = num;
                int len = 1;

                while(num_set.count(currentNum + 1)){
                    currentNum++;
                    len++;
                }

                ret = max(ret, len);
            }
        }
        return ret;
    }
};

哈希表

枚举数组中的每个数x,考虑以x为起点,不断匹配x+1,x+2,...是否存在,假设最长匹配到x+y,那么长度为y+1.

和为K的子数组

枚举超时

前缀和+哈希表优化

定义prei0...i里所有数的和,则prei由prei-1递推而来

cpp 复制代码
pre[i] = pre[i-1] + nums[i]

那么j...i这个子数组和为k可以转换为

cpp 复制代码
pre[i] - pre[j-1] == k

移动一下

cpp 复制代码
pre[j-1] = pre[i] - k

所以考虑以i结尾的和为k的连续子数组个数只需要统计有多少个前缀和prei - k的prej即可。

cpp 复制代码
class Solution{
	int subarraySum(vector<int>& nums, int k){
		unordered_map<int, int>mp;
		mp[0] = 1; //和为0的情况出现了一次
		int count = 0, pre = 0;
		for(auto&x : nums){
			pre += x;
			if(mp.find(pre-k) != mp.end()){
				count += mp[pre-k];
			}
			mp[pre]++;
		}
		return count;
	}
}

前缀和是指第一个元素到当前元素的所有元素之和,哈希表用于存储前缀和出现次数。

count记录和为k的连续子数组的个数。

旋转图像

cpp 复制代码
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        //转置
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                swap(matrix[i][j], matrix[j][i]);
            }
        }

        //两列交换 0 2 ---  0 3 1 2
        int midJ = n/2;
        for(int j=0; j<midJ; j++){
            for(int i=0; i<n; i++){
                swap(matrix[i][j], matrix[i][n-j-1]);
            }
        }
    }
};

搜索二维矩阵

暴力

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(matrix[i][j] == target){
                    return true;
                }
            }
        }
        return false;
    }
};

z字形查找

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        int x = 0, y = n-1;
        while(x < m && y >= 0){
            if(matrix[x][y] == target){
                return true;
            }
            else if(matrix[x][y] > target){
                y--;
            }
            else if(matrix[x][y] < target){
                x++;
            }
        }
        return false;
    }
};

反转链表

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr || head->next == nullptr){
            return head;
        }
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while(cur){
            ListNode* next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

和为K的子数组

给一个整数数组nums和一个整数k,统计并返回数组中和为k的子数组的个数。


前缀和+哈希表优化

定义prei0,...,i里所有数的和,则prei = prei-1 + numsi

j...,i子数组和为k可以转换为prei - prej-1 == k

转换为prej-1 = prei - k

所以我们考虑以i结尾的和为k的连续子数组的个数时,只需要统计有多少个前缀和为prei - k的prej即可。

cpp 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> mp; //<pre, count>
        mp[0] = 1;
        int count = 0, pre = 0;
        for(int num : nums){
            pre += num;
            if(mp.count(pre - k)){
                count += mp[pre-k];
            }
            mp[pre]++;
        }
        return count;
    }
};

回文链表

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> nums;
        while(head){
            nums.push_back(head->val);
            head = head->next;
        }
        int left = 0, right = nums.size() - 1;
        while(left < right){
            if(nums[left] != nums[right]){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};

环形链表

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == nullptr || head->next == nullptr){
            return false;
        }
        ListNode* slow = head;
        ListNode* fast = head->next;
        while(fast){
            if(slow == fast){
                return true;
            }`在这里插入代码片`
            if(fast->next != nullptr){
                fast = fast->next->next;
            }else{
                fast = nullptr;
            }
            slow = slow->next;
        }
        return false;
    }
};

二叉树的最大深度

二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root == nullptr){
            return 0;
        }
        int lDepth = maxDepth(root->left);
        int rDepth = maxDepth(root->right);
        return max(lDepth, rDepth)+1;
    }
};
相关推荐
weixin19970108016几秒前
[特殊字符] 1688开放平台API Sign签名算法详解(Java / Python / PHP 实现)
java·python·算法
未若君雅裁12 分钟前
JVM 垃圾回收算法与分代回收机制
java·jvm·算法
智者知已应修善业18 分钟前
【51单片机初始化D5-D8亮,每按键按下D1到D4全亮,再按下恢复,如此循环】2024-3-26
c++·经验分享·笔记·算法·51单片机
AC赳赳老秦34 分钟前
OpenClaw 助力技术面试:自动生成面试题、模拟面试、整理面试知识点
开发语言·python·面试·职场和发展·自动化·deepseek·openclaw
8Qi844 分钟前
LeetCode 4:寻找两个正序数组的中位数 —— 二分查找法
java·算法·leetcode·职场和发展·二分查找
林间码客1 小时前
智能旅行规划助手 — 实习面试问答手册
面试·职场和发展
8Qi81 小时前
LeetCode 32:最长有效括号 —— 栈 + 标记法 题解
java·数据结构·算法·leetcode·职场和发展··括号匹配
机器学习之心1 小时前
198种组合算法+优化CNN-LSTM+SHAP分析+新数据预测+多输出!深度学习可解释分析,强烈安利,粉丝必备
深度学习·算法·cnn-lstm·shap分析·198种组合算法
Tairitsu_H1 小时前
[LC优选算法#3] 滑动窗口 | 将x减到0的最⼩操作数 | ⽔果成篮 | 字⺟异位词
c++·算法·leetcode·滑动窗口
自由路飞1 小时前
Trellis 从 0 到 1 实战指南:让 AI 从"随便聊聊"变成"项目协作者"
面试