面试准备算法

找出数组的最大公约数

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的子数组

枚举超时

前缀和+哈希表优化

定义pre[i]为[0...i]里所有数的和,则pre[i]由pre[i-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的连续子数组个数只需要统计有多少个前缀和pre[i] - k的pre[j]即可。

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的子数组的个数。


前缀和+哈希表优化

定义pre[i]为[0,...,i]里所有数的和,则pre[i] = pre[i-1] + nums[i]

j...,i\]子数组和为k可以转换为pre\[i\] - pre\[j-1\] == k 转换为pre\[j-1\] = pre\[i\] - k 所以我们考虑以i结尾的和为k的连续子数组的个数时,只需要统计有多少个前缀和为pre\[i\] - k的pre\[j\]即可。 ```cpp class Solution { public: int subarraySum(vector& nums, int k) { unordered_map mp; // 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; } }; ``` ### 回文链表 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/dffea5a731534ae59552c0f99c9fbf98.png) ```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 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; } }; ```

相关推荐
_x_w32 分钟前
【17】数据结构之图及图的存储篇章
数据结构·python·算法·链表·排序算法·图论
anscos39 分钟前
Actran声源识别方法连载(二):薄膜模态表面振动识别
人工智能·算法·仿真软件·actran
-优势在我1 小时前
LeetCode之两数之和
算法·leetcode
WaitWaitWait011 小时前
LeetCode每日一题4.17
算法·leetcode
小媛早点睡1 小时前
贪心算法day9(合并区间)
算法·贪心算法
DataFunTalk1 小时前
Foundation Agent:深度赋能AI4DATA
前端·后端·算法
不是AI2 小时前
【Java编程】【计算机视觉】一种简单的图片加/解密算法
java·算法·计算机视觉
JiangJiang2 小时前
🧠 useMemo + memo + useContext 性能优化实战:从无感重渲染到丝滑体验
前端·react.js·面试
明月看潮生2 小时前
青少年编程与数学 02-016 Python数据结构与算法 23课题、分布式算法
分布式·python·算法·青少年编程·编程与数学
冠位观测者2 小时前
【Leetcode 每日一题】2176. 统计数组中相等且可以被整除的数对
数据结构·算法·leetcode