面试准备算法

找出数组的最大公约数

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;
    }
};
相关推荐
迷迭所归处1 分钟前
C++ —— 关于vector
开发语言·c++·算法
leon62531 分钟前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
CV工程师小林31 分钟前
【算法】BFS 系列之边权为 1 的最短路问题
数据结构·c++·算法·leetcode·宽度优先
Navigator_Z1 小时前
数据结构C //线性表(链表)ADT结构及相关函数
c语言·数据结构·算法·链表
Aic山鱼1 小时前
【如何高效学习数据结构:构建编程的坚实基石】
数据结构·学习·算法
天玑y1 小时前
算法设计与分析(背包问题
c++·经验分享·笔记·学习·算法·leetcode·蓝桥杯
sjsjs112 小时前
【数据结构-一维差分】力扣1893. 检查是否区域内所有整数都被覆盖
数据结构·算法·leetcode
redcocal2 小时前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘
码了三年又三年2 小时前
【算法】滑动窗口—找所有字母异位词
算法
山脚ice2 小时前
【Hot100】LeetCode—72. 编辑距离
算法·leetcode