面试准备算法

找出数组的最大公约数

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<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;
    }
};
相关推荐
半盏茶香22 分钟前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
徐子童26 分钟前
双指针算法习题解答
算法
想要打 Acm 的小周同学呀35 分钟前
LRU缓存算法
java·算法·缓存
阑梦清川41 分钟前
在鱼皮的模拟面试里面学习有感
学习·面试·职场和发展
劲夫学编程2 小时前
leetcode:杨辉三角
算法·leetcode·职场和发展
毕竟秋山澪2 小时前
孤岛的总面积(Dfs C#
算法·深度优先
浮生如梦_4 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
励志成为嵌入式工程师6 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉6 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer6 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法