算法
RAND7 构造 RAND 10
//rand7()
int rand10(){
int first,second;
while((first == rand7()) > 6);
while((second == rand7()) > 5);
return (first % 2 == 1) ? second : second + 5;
}
统计单词个数
#include<iostream>
#include<sstream>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
//通过STL的transform算法配合的toupper和tolower来实现该功能,只针对26个英文字母,其余的不会改变。
//输入的字符串中只考虑了空格这一种特殊字符,没有考虑其它特殊字符
int main()
{
string str;
getline(cin, str);
transform(str.begin(), str.end(), str.begin(), ::tolower);//将大写全部转换为小写
stringstream ss(str);
map<string, int> m;
map<string, int>::iterator it;
pair<map<string, int>::iterator, bool> flag;
while (ss >> str) //以空格为分隔符读入每一个单词
{
flag = m.insert(pair<string, int>(str, 1));
if ( ! flag.second)
{
it = m.find(str);
it->second++; //出现相同单词value值+1
}
}
multimap<int, string>m1;
for (it = m.begin(); it != m.end(); it++)
{
m1.insert(make_pair(it->second, it->first)); //将m中的单词转存到m1中,方便按value值排序
}
for (multimap<int,string>::iterator iter = --m1.end();iter != --m1.begin(); iter--) //降序输出
if(iter->first>3)
cout << iter->second << " " << iter->first<< endl;
return 0;
}
LRU缓存
struct DLinkedNode {
int key, value;
DLinkedNode* prev;
DLinkedNode* next;
DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}
DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
};
class LRUCache {
private:
unordered_map<int, DLinkedNode*> cache;
DLinkedNode* head;
DLinkedNode* tail;
int size;
int capacity;
public:
LRUCache(int _capacity): capacity(_capacity), size(0) {
// 使用伪头部和伪尾部节点
head = new DLinkedNode();
tail = new DLinkedNode();
head->next = tail;
tail->prev = head;
}
int get(int key) {
if (!cache.count(key)) {
return -1;
}
// 如果 key 存在,先通过哈希表定位,再移到头部
DLinkedNode* node = cache[key];
moveToHead(node);
return node->value;
}
void put(int key, int value) {
if (!cache.count(key)) {
// 如果 key 不存在,创建一个新的节点
DLinkedNode* node = new DLinkedNode(key, value);
// 添加进哈希表
cache[key] = node;
// 添加至双向链表的头部
addToHead(node);
++size;
if (size > capacity) {
// 如果超出容量,删除双向链表的尾部节点
DLinkedNode* removed = removeTail();
// 删除哈希表中对应的项
cache.erase(removed->key);
// 防止内存泄漏
delete removed;
--size;
}
}
else {
// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
DLinkedNode* node = cache[key];
node->value = value;
moveToHead(node);
}
}
void addToHead(DLinkedNode* node) {
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
}
void removeNode(DLinkedNode* node) {
node->prev->next = node->next;
node->next->prev = node->prev;
}
void moveToHead(DLinkedNode* node) {
removeNode(node);
addToHead(node);
}
DLinkedNode* removeTail() {
DLinkedNode* node = tail->prev;
removeNode(node);
return node;
}
};
链表排序
class Solution {
public:
ListNode* cut(ListNode* head, int n)
{
auto p = head;
while(--n && p){
p = p->next;
}
if(!p) return nullptr;
auto next = p->next;
p->next = nullptr;
return next;
}
ListNode* merge(ListNode* l1, ListNode* l2)
{
ListNode* dummy = new ListNode(-1);
auto p = dummy;
while(l1 && l2)
{
if(l1->val < l2->val)
{
p->next = l1;
p = l1;
l1 = l1->next;
}else
{
p->next = l2;
p = l2;
l2 = l2->next;
}
}
if(l1) p->next = l1;
if(l2) p->next = l2;
return dummy->next;
}
ListNode* sortList(ListNode* head) {
ListNode dummy(0);
dummy.next = head;
auto p = head;
int length = 0;
while(p){
++length;
p = p->next;
}
for(int size = 1; size<length; size<<=1)
{
auto cur = dummy.next;
auto tail = &dummy;
while(cur){
auto left = cur;
auto right = cut(left, size);
cur = cut(right, size);
tail->next = merge(left, right);
while(tail->next)
{
tail = tail->next;
}
}
}
return dummy.next;
}
};
字典序排序
class Solution {
public:
vector<int> res;
void dfs(int cur,int n){
if(cur>n) return;
res.push_back(cur);
for(int i=0; i<10; i++)
{
dfs(cur*10 + i, n);
}
}
vector<int> lexicalOrder(int n) {
for(int i =1; i<10; i++)
{
dfs(i, n);
}
return res;
}
};
二叉树个数
找出峰值
class Solution {
public:
int findPeakElement(vector<int>& nums) {
nums.push_back(INT_MIN);
int l = 0, r = nums.size() - 2;
while(l < r){
int m = (l+r) / 2;
if(nums[m] >= nums[m + 1] && (m == 0 || nums[m] >= nums[m - 1]))return m;
else if(nums[m] < nums[m+1]) l = m + 1;
else r = m - 1;
}
return l;
}
};
完全二叉树最右节点
/*
* 递归
* 求子树高度:如果当前根节点为叶子节点,则返回
* 如果左子树高度>右子树高度,则在左子树递归
* 否则在右子树递归
* 时间复杂度O(logN * logN) (求高度 * 遍历层数)
*/
class Solution {
public:
TreeNode* getLastNode(TreeNode* root) {
if(!root || root->left == nullptr)
return root;
int leftHeight = 0; // 左子树高度
TreeNode *node = root->left;
while (node){
node = node->left;
++ leftHeight;
}
int rightHeight = 0; // 右子树高度
node = root->right;
while(node){
node = node->left;
++ rightHeight;
}
if(leftHeight > rightHeight)
return getLastNode(root->left);
else
return getLastNode(root->right);
}
};
快速幂
// 计算a^n,a、n是正数,且为int16,实现函数
// shuaiying.gsy@alibaba-inc.com
// pkugsy@aliyun.com
long fun(long a, long n){
long long ans=1;
long long x = a;
while(n){
ans*=x;
x*=x;
n/=2;
}
return ans;
}
#include <climits>
#include <string>
//int16 的范围是-32768~32767。因为本题为正整数,所以a,n的范围是1~32767。
//unsigned long可表示的范围是0~2^64,本题最大值为2^(2^16),及2^(32767),超过了最大可表示的数。
//考虑用字符串代替大数,
string multiply(string num1, string num2) {
if (num1 == "0" || num2 == "0") {
return "0";
}
string ans = "0";
int m = num1.size(), n = num2.size();
for (int i = n - 1; i >= 0; i--) {
string curr;
int add = 0;
for (int j = n - 1; j > i; j--) {
curr.push_back(0);
}
int y = num2.at(i) - '0';
for (int j = m - 1; j >= 0; j--) {
int x = num1.at(j) - '0';
int product = x * y + add;
curr.push_back(product % 10);
add = product / 10;
}
while (add != 0) {
curr.push_back(add % 10);
add /= 10;
}
reverse(curr.begin(), curr.end());
for (auto &c : curr) {
c += '0';
}
ans = addStrings(ans, curr);
}
return ans;
}
string power(int a,int n)
{
string ans="1";
string x = to_string(a);
while(n!=0)
{
if(n%2) ans = mutiply(ans, x);
x = mutiply(x,x);
n/=2;
}
return ans;
}
快排
//快速排序(从小到大)
void quickSort(int left, int right, vector<int>& arr)
{
if(left >= right)
return;
int i, j, base;
i = left, j = right;
base = arr[left]; //取最左边的数为基准数
while (i < j)
{
while (arr[j] >= base && i < j)
j--;
while (arr[i] <= base && i < j)
i++;
if(i < j)
{
swap(arr[i], arr[j]);
}
}
//基准数归位
arr[left] = arr[i];
arr[i] = base;
quickSort(left, i - 1, arr);//递归左边
quickSort(i + 1, right, arr);//递归右边
}
堆排序
#include<iostream>
#include<vector>
using namespace std;
// 递归方式构建大根堆(len是arr的长度,index是第一个非叶子节点的下标)
void adjust(vector<int> &arr, int len, int index)
{
int left = 2*index + 1; // index的左子节点
int right = 2*index + 2;// index的右子节点
int maxIdx = index;
if(left<len && arr[left] > arr[maxIdx]) maxIdx = left;
if(right<len && arr[right] > arr[maxIdx]) maxIdx = right;
if(maxIdx != index)
{
swap(arr[maxIdx], arr[index]);
adjust(arr, len, maxIdx);
}
}
// 堆排序
void heapSort(vector<int> &arr, int size)
{
// 构建大根堆(从最后一个非叶子节点向上)
for(int i=size/2 - 1; i >= 0; i--)
{
adjust(arr, size, i);
}
// 调整大根堆
for(int i = size - 1; i >= 1; i--)
{
swap(arr[0], arr[i]); // 将当前最大的放置到数组末尾
adjust(arr, i, 0); // 将未完成排序的部分继续进行堆排序
}
}
int main()
{
vector<int> arr = {8, 1, 14, 3, 21, 5, 7, 10};
heapSort(arr, arr.size());
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<endl;
}
return 0;
}
合并k个有序链表
struct cmp {
bool operator () (ListNode *a, ListNode *b) {
return a->val > b->val;
}
};
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
priority_queue<ListNode*, vector<ListNode*>, cmp> q;
for (int i = 0; i < lists.size(); ++i) {
if (lists[i]) q.push(lists[i]);
}
ListNode *head = NULL, *pre = NULL, *tmp = NULL;
while (!q.empty()) {
tmp = q.top();
q.pop();
if (!pre) head = tmp;
else pre->next = tmp;
pre = tmp;
if (tmp->next) q.push(tmp->next);
}
return head;
}
};
k组一个反转链表
/**
* 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* reverseKGroup(ListNode* head, int k) {
stack<ListNode*> sta;
ListNode* dummy = new ListNode(0);
ListNode *p = dummy;
while(1){
int count = 0;
ListNode* tem = head;
while(tem!=nullptr&&count<k){
sta.push(tem);
tem = tem->next;
count++;
}
if(count!=k){
p->next = head;
break;
}
while(!sta.empty()){
p->next = sta.top();
sta.pop();
p = p->next;
}
p->next = tem;
head = tem;
}
return dummy->next;
}
};
反转链表
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = nullptr;
ListNode* cur = head;
while(cur){
ListNode* tem = cur->next;
cur->next = pre;
pre = cur;
cur = tem;
}
return pre;
}
};
反转区间链表
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode* pre = new ListNode(-1, head);
ListNode* res = pre;
int i=0;
while(i<left-1){
++i;
pre = pre->next;
}
ListNode* node = pre->next;
while(i<right-1){
ListNode* tmp = node->next;
node->next = tmp->next;
tmp->next = pre->next;
pre->next = tmp;
i++;
}
return res->next;
}
};
单例模式
class single{ //懒汉模式
private:
single(){}
static single* Instance;
public:
static single* getinstance()
{
if(Instance == NULL) {
Lock();
Instance = new single();
UnLock();
}
return Instance;
}
};
class singleton //饿汉模式
{
private:
singleton() {} //私有的构造函数
public:
static singleton* GetInstance()
{
static singleton Instance;
return &Instance;
}
};
合并有序链表
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* res = new ListNode(0);
ListNode *pi = res;
while(l1 && l2){
if(l1->val > l2->val){
pi->next = l2;
l2 = l2->next;
}else{
pi->next = l1;
l1 = l1->next;
}
pi = pi->next;
}
if(l1) pi->next = l1;
if(l2) pi->next = l2;
return res->next;
}
};
二叉树先序迭代遍历
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> result;
if (root == NULL) return result;
st.push(root);
while (!st.empty()) {
TreeNode* node = st.top(); // 中
st.pop();
result.push_back(node->val);
if (node->right) st.push(node->right); // 右(空节点不入栈)
if (node->left) st.push(node->left); // 左(空节点不入栈)
}
return result;
}
};
二叉树中序迭代遍历
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != NULL || !st.empty()) {
if (cur != NULL) { // 指针来访问节点,访问到最底层
st.push(cur); // 将访问的节点放进栈
cur = cur->left; // 左
} else {
cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
st.pop();
result.push_back(cur->val); // 中
cur = cur->right; // 右
}
}
return result;
}
};
二叉树转双向链表
class Solution {
public:
Node* head = new Node();
Node* ans = head;
void dfs(Node* root){
if(root == NULL){
return;
}
dfs(root->left);
head->right = root;
root->left = head;
head = head->right;
dfs(root->right);
}
Node* treeToDoublyList(Node* root) {
if(root == NULL) return NULL;
dfs(root);
head->right = ans->right;
ans->right->left = head;
return ans->right;
}
};
螺旋矩阵
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
int count = 1; // 用来给矩阵中每一个空格赋值
int offset = 1; // 每一圈循环,需要控制每一条边遍历的长度
int i,j;
while (loop --) {
i = startx;
j = starty;
// 下面开始的四个for就是模拟转了一圈
// 模拟填充上行从左到右(左闭右开)
for (j = starty; j < starty + n - offset; j++) {
res[startx][j] = count++;
}
// 模拟填充右列从上到下(左闭右开)
for (i = startx; i < startx + n - offset; i++) {
res[i][j] = count++;
}
// 模拟填充下行从右到左(左闭右开)
for (; j > starty; j--) {
res[i][j] = count++;
}
// 模拟填充左列从下到上(左闭右开)
for (; i > startx; i--) {
res[i][j] = count++;
}
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
startx++;
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset += 2;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if (n % 2) {
res[mid][mid] = count;
}
return res;
}
};
最长连续序列
//给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
//请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_map<int, int> mp;
int maxlen = 0;
for(int i=0; i<nums.size(); i++)
{
if(!mp.count(nums[i])){
int left = 0,right = 0;
if(mp.count(nums[i] - 1)){
left = mp[nums[i] - 1];
}
if(mp.count(nums[i] + 1)){
right = mp[nums[i] + 1];
}
int cur_len = 1 + left + right;
maxlen = max(maxlen, cur_len);
mp[nums[i]] = cur_len;
mp[nums[i] - left] = cur_len;
mp[nums[i] + right] = cur_len;
}
}
return maxlen;
}
};
丑数
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> factors = {2, 3, 5};
unordered_set<long> seen;
priority_queue<long, vector<long>, greater<long>> heap;
seen.insert(1L);
heap.push(1L);
int ugly = 0;
for (int i = 0; i < n; i++) {
long curr = heap.top();
heap.pop();
ugly = (int)curr;
for (int factor : factors) {
long next = curr * factor;
if (!seen.count(next)) {
seen.insert(next);
heap.push(next);
}
}
}
return ugly;
}
};