算法记录 & 牛客网 & leetcode刷题记录

  • 解题思路
  • STL容器
  • 常用算法模板
    • 堆排序
    • 插入排序
    • 快速排序
    • BFS层序遍历
  • 二叉树
    • JZ55 二叉树的深度
    • BST(binary search tree)的公共祖先
  • 回溯
    • JZ12 矩阵中的路径
  • 二分查找、排序
    • Leetcode-148 排序链表
    • BM18 二维数组中的查找
    • BM19寻找峰值
    • 295. 数据流的中位数
    • Sort a nearly sorted (or K sorted) array
  • 动态规划
    • DP5 连续子数组最大和
    • 664. Strange Printer(奇怪的打印机)
    • BM80 买卖股票的最好时机(一)
    • BM81 买卖股票的最好时机(二)
    • BM82 买卖股票的最好时机(三)
    • 329. 矩阵中的最长递增路径
  • 数组
    • leetcode 217存在重复元素
  • 链表
    • 141. 环形链表
  • 最大公约数
  • 面试题
    • 京东算法,好串
    • 艾方资产
    • 瑞银

解题思路

从最简单的case开始想,一般能找到规律。

如果从最简单的case不能找到思路,那么一般人不会,也不用死扎着这道题。

STL容器

map<type,type2> :有序的,如果不指定排序,最后一个元素最大
unordered_map:无序的
set:有序的
unordered_set:无序的
vector
priority_queue <int,vector,greater > q:从小到大排列
priority_queue <int,vector,less >q:从大到小排列

常用算法模板

堆排序

小顶堆:每次都把最大的调整到根部,最后把最大的放在数组末尾,最终形成的堆根部是最小的
大顶堆:每次都把最小的调整到根部,最后把最小的放在数组末尾,最终形成的堆根部是最大的

在优先队列里,

//小顶堆,top的时候返回元素最小的那个
priority_queue <int,vector<int>,greater<int> > q;
//大顶堆,top的时候返回元素最大的那个
priority_queue <int,vector<int>,less<int> >q;
``堆排序每次调整成大顶/小顶堆后,把堆顶元素放到数组末尾,然后继续调整大顶/小顶堆
```cpp
class HeapSort {public:void heapSort(vector<int>& arr) {if (arr.size() == 0) {return;}int len = arr.size();// 构建大顶堆,这里其实就是把待排序序列,变成一个大顶堆结构的数组buildMaxHeap(arr, len);// 交换堆顶和当前末尾的节点,重置大顶堆for (int i = len - 1; i > 0; i--) {swap(arr, 0, i);len--;heapify(arr, 0, len);}}void buildMaxHeap(vector<int>& arr, int len) {// 从最后一个非叶节点开始向前遍历,调整节点性质,使之成为大顶堆for (int i = (int)floor(len / 2) - 1; i >= 0; i--) {heapify(arr, i, len);}}void heapify(vector<int>& arr, int i, int len) {// 先根据堆性质,找出它左右节点的索引int left = 2 * i + 1;int right = 2 * i + 2;// 默认当前节点(父节点)是最大值。int largestIndex = i;if (left < len && arr[left] > arr[largestIndex]) {// 如果有左节点,并且左节点的值更大,更新最大值的索引largestIndex = left;}if (right < len && arr[right] > arr[largestIndex]) {// 如果有右节点,并且右节点的值更大,更新最大值的索引largestIndex = right;}if (largestIndex != i) {// 如果最大值不是当前非叶子节点的值,那么就把当前节点和最大值的子节点值互换swap(arr, i, largestIndex);// 因为互换之后,子节点的值变了,如果该子节点也有自己的子节点,仍需要再次调整。heapify(arr, largestIndex, len);}}void swap (vector<int>& arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}
};

插入排序

插入排序其实是冒泡排序的反向,插入排序从数组第二个元素开始,每加入一个元素,都将其和前面已有的元素进行比较,然后不断调整位置。

void insertionSort(vector<int> & data) {for (int i = 1; i < data.size(); i++) {for (int j = i; j >= 1; j--) {if (data[j] < data[j - 1]) {int tmp = data[j];data[j] = data[j - 1];data[j - 1] = tmp;}}}return;
}

快速排序

原理:每次随机将数组中的一个数,放到他指定的排序后的位置。
比如,把一个数A,放到数组的位置i,那么[0,i-1]的位置都是比A小的数,[i+1,size-1]都是比A大的数

class Solution {public:void qsort(vector<int>& nums,int start,int end,int k){int size=nums.size();int i=start,j=end,base=nums[start];if(size<=0) return;while(i<j){while(nums[j]<=base && i<j){j--;    }if(i<j) nums[i]=nums[j];while(nums[i]>=base && i<j) i++;if(i<j) nums[j]=nums[i];}nums[i]=base;if(i+1>k) qsort(nums,start,i-1,k);else if(i+1==k) return ;else qsort(nums,i+1,end,k);
}int findKthLargest(vector<int>& nums, int k) {int size=nums.size();qsort(nums,0,size-1,k);return nums[k-1];}};

BFS层序遍历

二叉树的层序遍历

/*** 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:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> res;if(root == nullptr){return res;}queue<TreeNode*> q;q.push(root);while(!q.empty()){int level_size = q.size();vector<int> v;while(level_size--){TreeNode* tmp_node = q.front();if (!(tmp_node->left== nullptr)){q.push(tmp_node->left);}if(!(tmp_node->right == nullptr)){q.push(tmp_node->right);}q.pop();v.push_back(tmp_node->val);} res.push_back(v);}return res;}
};

二叉树

JZ55 二叉树的深度

关键词:二叉树、深度优先遍历、递归

自己写的笨蛋方法:

/*
struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;TreeNode(int x) :val(x), left(NULL), right(NULL) {}
};*/
class Solution {public:int max_depth = 0;int now_depth = 0;int TreeDepth(TreeNode* pRoot) {if(pRoot == NULL){return max_depth;}this->now_depth++;if(now_depth>max_depth){max_depth=now_depth;}this->TreeDepth(pRoot->left);this->TreeDepth(pRoot->right);this->now_depth--;return max_depth;}
};

优秀解答:

  1. 递归解法
class Solution {public:int TreeDepth(TreeNode* pRoot){if(!pRoot) return 0 ;return max(1+TreeDepth(pRoot->left), 1+TreeDepth(pRoot->right));}
};
  1. BFS解法
import java.util.Queue;
import java.util.LinkedList;public class Solution {public int TreeDepth(TreeNode pRoot){if(pRoot == null){return 0;}Queue<TreeNode> queue = new LinkedList<TreeNode>();queue.add(pRoot);int depth = 0, count = 0, nextCount = 1;while(queue.size()!=0){TreeNode top = queue.poll();count++;if(top.left != null){queue.add(top.left);}if(top.right != null){queue.add(top.right);}if(count == nextCount){nextCount = queue.size();count = 0;depth++;}}return depth;}
}

BST(binary search tree)的公共祖先

BST的公共祖先

回溯

其实回溯就是递归

解题的时候,如果遇到给的函数参数不够,可以另自己起一个函数

JZ12 矩阵中的路径

我的答案

class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param matrix char字符型vector<vector<>> * @param word string字符串 * @return bool布尔型*/int now=0;bool flag = false;stack<int*> s;vector<vector<bool>> v;bool hasPath(vector<vector<char> >& matrix, string word) {// write code hereif(matrix.size()==0 || word.size()==0 || matrix[0].size()==0){return false;}if(now == 0){v.resize(matrix.size(), vector<bool>(matrix[0].size()));}if(word[now] == '\0'){flag=true;return flag;}if(now ==0){for(int i = 0;i<matrix.size();i++){for(int j=0; j<matrix[0].size();j++){if(flag){break;}if(matrix[i][j]==word[now]){now++;int arr[2]={i,j};s.push(arr);v[i][j] = true;if(hasPath(matrix, word)){return flag;  }s.pop();now--;v[i][j]=false;}}}}else{int* arr = s.top();int i = arr[0];int j = arr[1];if(i!=0 &&  matrix[i-1][j] == word[now] && v[i-1][j]!=true){now++;int tmp[2] = {i-1, j};s.push(tmp);v[i-1][j]= true;if(hasPath(matrix, word)){return flag;}v[i-1][j]= false;s.pop();now--;}if(i!=matrix.size()-1 &&  matrix[i+1][j] == word[now] && v[i+1][j]!=true){now++;int tmp[2] = {i+1, j};s.push(tmp);v[i+1][j]= true;if(hasPath(matrix, word)){return flag;}v[i+1][j]= false;s.pop();now--;}if(j!=matrix[0].size()-1 &&  matrix[i][j+1] == word[now] && v[i][j+1]!=true){now++;int tmp[2] = {i, j+1};s.push(tmp);v[i][j+1]= true;if(hasPath(matrix, word)){return flag;}v[i][j+1]= false;s.pop();now--;}if(j!=0 &&  matrix[i][j-1] == word[now] && v[i][j-1]!=true){now++;int tmp[2] = {i, j-1};s.push(tmp);v[i][j-1]= true;if(hasPath(matrix, word)){return flag;}v[i][j-1]= false;s.pop();now--;}}return flag;}
};

高分答案

import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param matrix char字符型二维数组 * @param word string字符串 * @return bool布尔型*/public boolean hasPath (char[][] board, String word) {// write code hereint  length1=board[0].length;//列数int  length2=board.length;//行数for(int i =0; i<length2;i++){for(int j=0;j<length1;j++){if(board[i][j]==word.charAt(0))if(dfs(board,i,j,word,0))return true;}}return false;}public boolean dfs(char[][] board,int i, int j, String word, int u){int  length1=board[0].length;//列数int  length2=board.length;//行数//失败:先判断边界值if(i<0||i>=length2||j<0||j>=length1||board[i][j]!=word.charAt(u)){return false;}//成功:遍历到最后一个if(u==word.length()-1)return true;//覆盖原来防止重复char temp = board[i][j];board[i][j]= '#';//递归调用boolean res = dfs(board,i-1,j,word,u+1) || dfs(board,i+1,j,word,u+1) || dfs(board,i,j-1,word,u+1)|| dfs(board,i,j+1,word,u+1) ;//递归结束board[i][j]= temp;return res;}
}

总结:
回溯刚开始都要判断结束 && 判断边界 && 判断条件

接下来再调用自己。

有没有走过可以先覆盖原来的,之后回溯出来的时候再写回原来的
(这样就避免了还要自己初始化一个数组判断是否走过)

二分查找、排序

二分诀窍:

  1. 找到二分开始的位置
  2. 找到二分前进的方向

关于左开右闭,左闭右开,左闭右闭
【玩转二分查找Ⅰ】左闭右闭型,左开右闭型,左闭右开型(动图演绎)

核心是,中间值的取法不同 以及 while循环内部的判断方式不同

Leetcode-148 排序链表

leetcode-排序列表题目详情
总结:使用归并排序
链表找到中间位置:是用一个快指针,一个慢指针。

卡了很久的一个点:

if(first_pointer == nullptr) return second_pointer
elsereturn first_pointer

这是错误的,因为忽略了 first_pointer和second_pointer都有值的情况


/*** 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* sortList(ListNode* head) {if(head == nullptr || head->next==nullptr){return head;} ListNode* first_pointer=head;ListNode* second_pointer=head->next;// 找到中间的位置while((second_pointer!=nullptr) && (second_pointer->next!=nullptr) ){first_pointer = first_pointer->next;second_pointer = second_pointer->next;if(second_pointer->next != nullptr){second_pointer = second_pointer->next;}}ListNode* next_pointer = first_pointer->next;first_pointer->next =nullptr;head = sortList(head);next_pointer = sortList(next_pointer);return Merge(head,next_pointer);}ListNode* Merge(ListNode* first_pointer, ListNode* second_pointer){ListNode* head;ListNode* tick;if(first_pointer == nullptr){return second_pointer;}if(second_pointer == nullptr){return first_pointer;}if(first_pointer->val < second_pointer->val){head=first_pointer;tick=first_pointer;first_pointer = first_pointer->next;}else{head=second_pointer;tick=second_pointer;second_pointer = second_pointer->next;}while(first_pointer!=nullptr && second_pointer!=nullptr){if(first_pointer->val < second_pointer->val){tick->next= first_pointer;first_pointer = first_pointer->next;tick = tick->next;}else{tick->next = second_pointer;second_pointer = second_pointer->next;tick = tick->next;}}if(first_pointer==nullptr){tick->next =second_pointer;}else{tick->next=first_pointer;}return head;}};

BM18 二维数组中的查找

矩阵中,行和列都是递增,那么可以找左下,或者右上的元素开始。
复杂度:O(n+m)

class Solution {public:bool Find(int target, vector<vector<int> > array) {int r = array.size();if(r == 0){return false;}int col = array[0].size();if(col == 0){return false;}int i = 0, j =col-1;while(i<=r-1 && j>=0 ){if(array[i][j] == target){return true;}else if(array[i][j] >target){j--;}else if(array[i][j]<target){i++;}}return false;}
};

BM19寻找峰值

复杂度O(logn)
思想: 上坡一定有波峰,下坡不一定有波峰

class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param nums int整型vector * @return int整型*/int findPeakElement(vector<int>& nums) {// write code hereint right = nums.size()-1;int left = 0;while(left<right){int mid = (left+right)/2;if(nums[mid]>nums[mid+1]){right = mid;}else{left = mid+1;}}return right;}
};

295. 数据流的中位数

295.数据流的中位数

思想: 维护两个堆,一个大顶堆(堆顶是最大的元素),一个是小顶堆(堆顶是最小的元素)。

每个堆都存储一半的元素,大顶堆的元素总是小于等于小顶堆的元素。

那么中位数就可以通过大顶堆堆顶和小顶堆堆顶元素来判断。

class MedianFinder {public:// 小顶堆,堆顶是最小的元素priority_queue<int, vector<int>, greater<int>> big;// 大顶堆,堆顶是最大的元素priority_queue<int, vector<int>, less<int>> small;MedianFinder() {}void addNum(int num) {big.push(num);small.push(big.top());big.pop();if(small.size()>big.size()){big.push(small.top());small.pop();}}double findMedian() {if(big.size() == small.size()){return (big.top() +small.top())/2.0; }else{return big.top();}}
};/*** Your MedianFinder object will be instantiated and called as such:* MedianFinder* obj = new MedianFinder();* obj->addNum(num);* double param_2 = obj->findMedian();*/

Sort a nearly sorted (or K sorted) array

题目描述:对一个元素正确位置,离自己至多K个距离的数组,进行排序
提示:堆排序,建立一个k+1大小的堆(因为K+1个堆里,肯定最顶上那个是排序好的,把他取出来放在正确的位置即可)

答案-Sort a nearly sorted (or K sorted) array

动态规划

所以在DP的实践中很重要的就是递推关系边界条件
1. 边界条件
所谓边界条件就是最简单的情况。
2. 递推关系
所谓递推关系就是如果你已经知道这么多,再多给你一个,你怎么得到。
(状态转移方程)

状态定义、状态转移方程

DP5 连续子数组最大和

状态定义: array[i] 表示数组连续到下标为i为止的连续数组最大和
(注意区别于整个数组的连续数组最大和, 或者说 array[i]代表以第 i 个数结尾的子数组最大连续和)
状态转移方程: state[i] = max(state[i-1]+array[i], array[i])
因为最终求的是整个数组的最大值,所以要使用max_num来存储最大值

#include<bits/stdc++.h>
using namespace std;
int main(){int n;cin>>n;vector<int> array(n, 0);vector<int> state(n,INT_MIN);cin>>array[0];state[0] = array[0];int max_num = array[0];for(int i=1;i<n;i++){cin>>array[i];state[i] = max(state[i-1]+array[i],array[i]);max_num = max(max_num,state[i]);}cout<<max_num<<endl;return 0;
}

664. Strange Printer(奇怪的打印机)

题解

class Solution {public:int strangePrinter(string s) {int size = s.size();if(size == 0){return 0;}vector<vector<int>> v(size, vector<int>(size, INT_MAX));for(int i=size-1;i>=0;i--){for(int j=i;j<=size-1;j++){// 分开打印v[i][j] = ((i==j)? 1: 1+v[i+1][j]);for(int k=i+1;k<j;k++){if(s[i] == s[k]){v[i][j] = min(v[i][j], v[i+1][k]+v[k+1][j]);}}if(s[i] == s[j] && i!=j){v[i][j] = min(v[i][j], v[i+1][j]);}}}return v[0][size-1];}
};

BM80 买卖股票的最好时机(一)

这种买入必须在卖出前面的,即当前位置的值只和前面有关的,非常适合于一次遍历

class Solution {public:/*** * @param prices int整型vector * @return int整型*/int maxProfit(vector<int>& prices) {// write code hereint min_price = INT_MAX;int profit = 0;int size = prices.size();for(int i=0;i<size;i++){profit = max(profit, prices[i] - min_price);min_price = min(min_price,prices[i]);}return profit;}
};

BM81 买卖股票的最好时机(二)

class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可* 计算最大收益* @param prices int整型vector 股票每一天的价格* @return int整型*/int maxProfit(vector<int>& prices) {// write code hereint profit = 0;for(int i =1; i<prices.size();i++){int tmp = prices[i] -prices[i-1];if(tmp>0){profit+=tmp;}}return profit;}
};

BM82 买卖股票的最好时机(三)

class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可* 计算最大收益* @param prices int整型vector 股票每一天的价格* @return int整型*/int maxProfit(vector<int>& prices) {// write code hereint dp0 = 0;int dp1 = -prices[0];int dp2 = 0;int dp3 = -prices[0];int dp4 = 0;      for(int i=1;i<prices.size();i++){int dp0_0 = dp0;int dp1_1 = max(dp1, dp0 - prices[i]);int dp2_2 = max(dp2, dp1 + prices[i]);int dp3_3 = max(dp3, dp2 - prices[i]);int dp4_4 = max(dp4, dp3 + prices[i]);dp0 = dp0_0;dp1 = dp1_1;dp2 = dp2_2;dp3 = dp3_3;dp4 = dp4_4;
//             dp0 = dp0;
//             dp1 = max(dp1, dp0 - prices[i]);
//             dp2 = max(dp2, dp1 + prices[i]);
//             dp3 = max(dp3, dp2 - prices[i]);
//             dp4 = max(dp4, dp3 + prices[i]);}   return dp4;}
};

329. 矩阵中的最长递增路径

leetcode 329 矩阵中的最长递增路径

方法1: DFS + 动态规划

class Solution {public:vector<vector<int>> directions{{0,-1},{0,1},{1,0},{-1,0}};int longestIncreasingPath(vector<vector<int>>& matrix) {int row_num = matrix.size();if(row_num == 0){return 0;}int col_num = matrix[0].size();if(col_num == 0){return 0;}vector<vector<int>> memo(row_num, vector<int>(col_num , 0));int max_length = 0;for(int i= 0; i<row_num;i++){for(int j=0;j<col_num;j++){max_length = max(max_length, dfs(matrix, i, j, memo));}}return max_length;}int dfs(vector<vector<int>>& matrix, int row, int col, vector<vector<int>>& memo){if(memo[row][col] !=0){return memo[row][col];}memo[row][col]++;for(int i=0;i<directions.size();i++){int new_row = directions[i][0] + row;int new_col = directions[i][1] + col;if(new_row >=0 && new_col>=0 && new_row<memo.size() && new_col < memo[0].size()){if(matrix[new_row][new_col] > matrix[row][col]){memo[row][col] = max(memo[row][col], dfs(matrix, new_row, new_col, memo)+1);}}}return memo[row][col];}};

方法2:拓扑排序 + 动态规划
注意,这里是从出度为0的

class Solution {public:vector<vector<int>> dirs = {{0,-1},{0,1}, {1,0},{-1,0}};int longestIncreasingPath(vector<vector<int>>& matrix) {if (matrix.size() == 0 || matrix[0].size() == 0) {return 0;}int row_num = matrix.size();int col_num = matrix[0].size();vector<vector<int>> outdegrees(row_num, vector<int>(col_num, 0));queue<pair<int,int>> q;for(int i=0; i<row_num; i++){for(int j=0; j<col_num; j++){for(int dir=0;dir<dirs.size();dir++){int newRow = i+dirs[dir][0];int newCol = j+dirs[dir][1];if(newRow>=0 && newCol>=0 && newRow<row_num && newCol < col_num && matrix[i][j] < matrix[newRow][newCol]){outdegrees[i][j]++;}}}}for(int i=0;i<row_num;i++){for(int j=0;j<col_num;j++){if(outdegrees[i][j] == 0){q.push(pair<int,int>(i,j));}}}int ans =0;//BFSwhile(!q.empty()){ans++;int tmp_size = q.size();for(int _=0;_<tmp_size;_++){pair<int, int> e = q.front();q.pop();int row = e.first;int col = e.second;for(int dir=0;dir<dirs.size();dir++){int newRow = row + dirs[dir][0];int newCol = col + dirs[dir][1];
\if(newRow>=0 && newCol>=0 && newRow<row_num && newCol < col_num && matrix[row][col] > matrix[newRow][newCol]){outdegrees[newRow][newCol]--;if(outdegrees[newRow][newCol] == 0){q.push(pair<int, int>(newRow, newCol));}}}}}return ans;}
};

数组

leetcode 217存在重复元素

使用哈希表
unordered_set s;

链表

141. 环形链表

链表判环

/**
* 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 == NULL){return false;}ListNode* slow;ListNode* fast;slow = fast = head;while(fast!= NULL && fast->next!= NULL){slow = slow->next;fast = fast->next->next;if(slow == fast){return true;}}return false;}
};

最大公约数

There are N chocolates in a circle. Count the number of chocolates you will eat.
题目

这道题的意思是,将N个巧克力排成一圈,我们每次都能走0, 1M, 2M, 3M, …, kM次。求能吃到的巧克力数量。

能吃到的巧克力数量 = (N和M的最小公倍数 / M)
而因为:
N和M的最小公倍数 = N*M / (N和M的最大公约数)

因此最后
能吃到的巧克力数量=N/(N和M的最大公约数)

面试题

京东算法,好串

小红定义一个字符串为好串,当且仅当相邻两个字母不相同。小红拿到了一个仅由’r’、‘e’、'd’三种字符组成的字符串,她有一个魔法:将相邻两个相同的字母同时删除,并在其位置生成任意一个字母(‘r’、‘e’、‘d’)三种中的一种。例如,对于字符串“dedd”,小红可以选择中间两个相邻字母“dd”,将其变成"r",此时字符串变为“der”。小红希望将给定的字符串变成“好串”。

输入一个长度不超过200000的、仅由’r’、‘e’、'd’三种字符组成的字符串。输出一个整数,代表操作的最小次数。

input:
rrrr

output:
1

s = input()
n = len(s)
i = 0
ans = 0
while i < n:cnt = 1while i< n-1 and s[i] == s[i+1]:cnt+=1i+=1i+=1ans+=(cnt+1) // 3
print(ans)
  1. 如果有2个r连续。 那么可以直接替换成和左右两边不冲突的
  • case 1
    d rr e -> d r e
  • case2
    d rr d -> d r d
  1. 如果有3个r连续。 那么替换1次:
  • case 1
    d rrr d -> d e r d
  • case 2
    d rrr e -> d e r e
  1. 如果有4个r连续。那么替换1次:
  • case 1
    d rrrr d -> d r d r d
  • case 2
    d rrrr e -> d r d r e
  1. 如果有5个r连续。那么:
  • case 1
    d rrrrr d -> d e r e d

从以上开出来是以3为周期的

艾方资产

把N*M的棋盘分割成若干个1*2的长方形,有多少种方案

瑞银

求一个数字序列里面和最大的子序列,它的和是多少?

算法记录 牛客网 leetcode刷题记录相关推荐

  1. 牛客网-前端刷题记录(中等级)

    文章目录 HJ16 购物单 HJ17 坐标移动√ HJ20 密码验证合格程序√ HJ24 合唱队√√ HJ26 字符串排序√√ HJ27 查找兄弟单词√ HJ29 字符串加解密√√ HJ32 密码截取 ...

  2. 牛客网-前端刷题记录

    文章目录 自守数.质数(素数).约数.完全数 HJ99 自守数√ HJ6 质数因子√√ HJ56 完全数计算√√ HJ60 查找组成一个偶数最接近的两个素数√ 数列 HJ100 等差数列√ HJ76 ...

  3. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合...

    不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...

  4. 牛客网SQL刷题笔记(MySQL)

    牛客网SQL刷题笔记(MySQL) 此博客集合LeetCode.牛客网常见的题型及其解法,侵删 目录 牛客网SQL刷题笔记(MySQL) 类型1:查找排名第几的数据 SQL2 查找入职员工时间排名倒数 ...

  5. 牛客网C++刷题 万能头文件

    牛客网C++刷题 万能头文件 最近在牛客网刷题,涉及到C++编码时有时不记得头文件名称,这时可以使用 #include<bits/stdc++.h> 这个万能头文件来代替. 特此记录一下.

  6. 牛客网Java刷题知识点之关键字static、static成员变量、static成员方法、static代码块和static内部类...

    不多说,直接上干货! 牛客网Java刷题知识点之关键字static static代表着什么 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个"伪全局"的概 ...

  7. 牛客网Java刷题知识点之构造函数可以调用一般函数,但是一般函数不可以直接调用构造函数...

    不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...

  8. 牛客网Java刷题知识点之ArrayList 、LinkedList 、Vector 的底层实现和区别

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  9. 牛客网Veirlog刷题答案目录(持续更新)

    牛客网Veirlog刷题答案目录(持续更新) 基础篇 进阶篇 基础篇 1.VL1--四选一多路选择器 2.VL2--异步复位的串联T触发器 3.VL3--奇偶校验 4.VL4--移位运算与乘法 5.V ...

最新文章

  1. 不懂编程可以自学python吗-python教程看完了,还是不会编程?
  2. nginx的启动初始化过程(一)
  3. Node.js 框架
  4. 抢椅子游戏java_游戏教案小班抢椅子
  5. 神策数据入选“2019 全球企服科技创新 Top50”
  6. 关于压缩工具 7z(7-zip) 的选项 -w(设置工作目录)的解读
  7. linux中统计java数量,linux 统计当前目录下文件数
  8. 凯撒密码pythin密码_凯撒密码术
  9. LINUX X11剪贴板/clipboard访问C代码范例
  10. 本地项目上传github的巧妙方法
  11. 主动降噪python_主动降噪(Active Noise Control)
  12. 李开复,活在AI与人群里
  13. 维特WT931 姿态角度传感器(陀螺仪)使用记录
  14. 安全的远程访问是保护知识产权的关键
  15. 它来了它来了!2020深度学习硬核技术干货集锦!
  16. 校招面试真题 | 实习生和应届生有什么区别?
  17. 【bcrypt.dll下载】bcrypt.dll丢失怎么修复
  18. 国内国外主流的CMS
  19. 如何在Deepin Linux下安装Docker容器经验分享
  20. 同城外卖跑腿系统源码分析

热门文章

  1. 什么叫工作到位?听听人民日报怎么说 | 职场--带队伍--必知必会
  2. 单片机ADC检测4-20mA电路,以及计算方法
  3. php蔬菜农村电商系统_农产品电子商务网站开发(PHP+MySQL+JavaScriptHTML)
  4. [JavaScript]解构赋值详解
  5. 2023华为od统一考试B卷【评论转换输出】C++
  6. 漫画|讲解一下如何写简历项目
  7. java切点类编写_SpringAOP切点函数实现原理详解
  8. 【Linux】用户不在sudoers文件中
  9. 江西事业单位计算机专业知识真题,2015年江西事业单位考试计算机每日练习题(1月27日)...
  10. MobaXterm的Anaconda的安装