找出数组的最大公约数
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;
}
};