算法

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;
    }
};

image-20220312120503624

链表排序

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;
    }
};
posted @ 2022-03-24 09:04  iloveacm  阅读(49)  评论(0编辑  收藏  举报