面试准备算法

找出数组的最大公约数

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;
    }
};
相关推荐
cwj&xyp25 分钟前
Python(二)str、list、tuple、dict、set
前端·python·算法
古木201931 分钟前
前端面试宝典
前端·面试·职场和发展
xiaoshiguang35 小时前
LeetCode:222.完全二叉树节点的数量
算法·leetcode
爱吃西瓜的小菜鸡5 小时前
【C语言】判断回文
c语言·学习·算法
别NULL5 小时前
机试题——疯长的草
数据结构·c++·算法
TT哇5 小时前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
yuanbenshidiaos6 小时前
C++----------函数的调用机制
java·c++·算法
唐叔在学习6 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA7 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
chengooooooo7 小时前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展