c++软件开发算法

数组:

//在连续空间存储相同类型的元素。
1、定义数组:int arr1[5] = {1 , 2, 4 ,5};   int a[100] = {0};
2、数组的大小: n = sizeof a/sizeof(int)

1、最大连续的1的个数

//输入:[1,1,0,1,1,1]  输出:3
class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
        int count =0;
        int maxcount = 0;
        for(int i = 0 ;i < nums.size();i++) {
            if(nums[i] == 1) {
                count++;
            }
            else {
                maxcount = max(maxcount,count);
                count = 0;
            }
        }
        maxcount = max(maxcount,count);  //最大连续的1的个数可能出现在最后
        return maxcount;
    }
};

2、移动零

//输入: [0,1,0,3,12]   输出: [1,3,12,0,0]
//第一种直接覆盖
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int n = nums.size();
        int index = 0;
        for(int i=0;i < n;i++) {
            if(nums[i] != 0) {
                nums[index++] = nums[i];
            }
        }
        while(index < n) {
            nums[index++] =0;
        }
    }
};

3、移除元素

//移除一个数组中所有等于val的元素,并返回数组新的长度
//输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2]
//思想和上一个一样,主要就是可以看成2个数组,一个指向一个,然后寻找符合的元素按照index顺序排好,其余元素添0.
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int  n = nums.size();
        int index = 0;
        for(int i = 0 ; i < n; i++)  {
            if(nums[i] != val) {
                nums[index++] =nums[i];
            }
        }
        return index;
    } 
};

链表:

1、创建链表  2、添加元素 3、访问元素 
4、查找元素  5、删除元素 6、链表长度
    //链表定义

ListNode* head = new ListNode(5);
//ListNode* head = new ListNode();
//head->val = 5;  数值为5 的节点

//用来定义单链表结构
struct node
{
	int data; //数据域
	node* next; //指针域
};
class list
{
	node* head;
public:
	list()
	{
		head = new node;//创建堆区  指针head指向node堆区的首地址,然后让其指向空
		head->next = NULL;  //NUll为一个空地址
	}
};

1、删除链表元素

//输入:head = [1,2,6,3,4,5,6], val = 6  输出:[1,2,3,4,5]
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 * };

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
       
        //删除头节点 
        while (head !=NULL && head->val == val) {
            ListNode * tmp = head;
            head  = head->next;
            delete tmp;                
        }
        //删除非头结点
        ListNode *p = head;
        while(p  != NULL  && p->next != NULL ) {
            if(p->next->val == val)  {
                ListNode *tmp= p->next;
                p->next = p->next->next;
                delete tmp;
            }
            else {
                p =p->next;
            }
        }
        return head;    
    }
};

2、反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

3、判断链表是否有环

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,说明有环
            if (slow == fast) return true;
        }
        return false;
    }
};
//slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z)
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2; // 返回环的入口
            }
        }
        return NULL;
    }
};

4、链表倒数第k个元素

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyNode = new ListNode(0, head);
        ListNode* slow = dummyNode;
        ListNode* fast = dummyNode;
        //令slow和fast距离相差n
        while (n--) {
            fast = fast->next;
        }
        //令fast最终停留在尾结点,因为slow和fast相差n,则slow位置为尾结点的前n个位置,即slow为整个链表倒数第n+1个结点,也就是第n个结点的前驱结点
        while (fast->next) {
            fast = fast->next;
            slow = slow->next;
        }
        //令倒数第n个结点的前驱结点指向其下一结点的next
        slow->next = slow->next->next;
        return dummyNode->next;
    }
};

队列:

//先进先出  相当于一个管道  一端进一端出
queue容器 相当于队列,先进先出   
q.push() //队尾进入数据   q.back() //返回最后一个元素
q.pop() //队头出数据      q.front() //返回第一个元素
//单端队列  一个口只能进,一个口可以出
//插入 只能插到最后   删除只能删除头 
//创建队列  添加元素  获取元素  删除元素 判断队列是否为空  队列长度  遍历队列(边遍历边删除)

1、最近的请求次数

//["RecentCounter", "ping", "ping", "ping", "ping"][[], [1], [100], [3001], [3002]]
//输出:[null, 1, 2, 3, 3]
class RecentCounter {
public:
    RecentCounter() {}
//使用队列,一直检查队列头部和插入时间是否大于3000,大于就弹出
    int ping(int t) {
       q.push(t); 
       while( t - q.front() > 3000) {
           q.pop();  
       }
       return q.size();
    }
private:
     queue<int> q;
};

2、滑动窗口最大值

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> q;
        //在队列后面添加数据,把前面数据小的全部删除。
        vector<int> ans; 
        for(int i = 0 ;i < nums.size(); i++) {
            //当前遍历的元素的值比队尾大,让队尾元素出去  
            while(! q.empty()  && q.back() <  nums[i] ) {
                 q.pop_back();
            }
            //当遍历的元素入栈,那么队列的元素头部最大
            q.push_back(nums[i]);
            //如果窗口满状态,就可以得到窗口最大值啦
            if(i >= k - 1) {
                ans.push_back(q.front());
                if(nums[i - k + 1] == q.front()) {
                    q.pop_front();
                }
            }
        }
        return ans;
    }
};

栈(stack):

先进后出   : A B C  ->  C B A   
1、怎么创建栈

1、有效括号

class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        if(n % 2 == 1) return false;
       unordered_map<char, char> pair = { {')', '('},{']', '['},{'}', '{'}};
        stack<char> stk;
        for(char ch : s) { //在s中遍历 字符串s中全部字符的存在 
        //左括号压进栈,后面进入的先匹配
            if(pair.count(ch)) {  //字符ch对应键值个数的多少
               if(stk.empty() || stk.top() != pair[ch]) return false; 
               stk.pop();
            }
            else  stk.push(ch);
        }
        return stk.empty();
    }
};

class Solution {
public:
    bool isValid(string s) {
        stack<char> st; 
        for(int i = 0; i < s.size(); i++) {   // if else  互斥 只能执行一个
            if (s[i] == '(') st.push(')'); //先进匹配,如果 有左括号,就压进去右括号,
            else if (s[i] == '{') st.push('}');
            else if (s[i] == '[') st.push(']');
            else if (st.empty() || st.top() != s[i]) return false;
            else st.pop(); // st.top() 与 s[i]相等,栈弹出元素
        }
        return st.empty();
    }    
};

2、下一个更大元素

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        stack<int> s; //记录数组的值
        //主要就先求出,主数组的下一个更大元素,然后直接匹配
        //转换成查找后面元素是否大的问题
        unordered_map <int,int> map; //存放下一个最大值
        for(int i = nums2.size() - 1 ;i >=0; i--) {
           while(! s.empty() && s.top() <= nums2[i]) {
               s.pop();
           }
           map[nums2[i]] = s.empty() ? -1: s.top();
           s.push(nums2[i]);
        }  
        for(int i = 0; i < nums1.size();i++) {
            nums1[i] = map[nums1[i]];
        }
        return  nums1;
    }
};

哈希表:

哈希表:key : value   可以通过key得到value  
通过key值  哈希函数对应,找到内存地址  
1、哈希碰撞:两个不同的key值对应同一个哈希函数,得到相同的内存地址。(链表)

1、存在重复元素

// 输入: [1,2,3,1] 输出: true
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        for(int  i = 0;i < nums.size()-1; i++) {
               if(nums[i] == nums[i+1]) {  
                   return true;
               }  
        }
        return false;
    }
};
 
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> s;
        for(int x: nums) {
            if(s.find(x) != s.end())  //find这个函数,找不到会返回end();  != :找到这个元素了
               return true;
            s.insert(x);
        }
        return false;
    }
};

2、找不同

//输入:s = "abcd", t = "abcde"  输出:"e"
class Solution {
public:
    char findTheDifference(string s, string t) {
       vector<int> v(26,0);
       for(char x : s) {
           v[x-'a']++; 
       }
       for(char x : t) {
           v[x- 'a']--;
           if(v[x - 'a'] < 0) {
               return x;
           }
       }
        return ' '; 
    }
};

集合set:

1、检查某个元素是否存在
2、重复元素     

1、设计哈希集合

class MyHashSet {
public:
    /** Initialize your data structure here. */
    MyHashSet() {
        map.resize(1000010,0);
    }  
    void add(int key) {
        map[key] = true;
    }
    void remove(int key) {
         map[key] = false;
    } 
    /** Returns true if this set contains the specified element */
    bool contains(int key) {
        return  map[key];
    }
private:
     vector<bool> map;
};

树:

//二叉树定义:
struct TreeNode {
    int val;
    TreeNode *right;
    TreeNode *left;
    TreeNode(int x) :val(x), left(NULL) ,right(NULL) {}   //构造函数
};

1、递归法 前中后遍历

//前中后遍历:
clss Solution {
public:
        void traversal(TreeNode *cur,vector<int> &vec) {  //前序遍历
            if(cur == NULL) return ;
            vec.push_back(cur->val);
            traversal(cur->left,vec);
            traversal(cur->right,vec);
        }
        void travesal(TreeNode *cur,vector<int> &vec) {   //中序遍历
            if(cur == NULL) return;
            travesal(cur->left,vec);
            vec.push_back(cur->val);
            travesal(cur->right,vec);
        }
        void travesal(TreeNode *cur,vector<int> &vec) {   //后序遍历
            if(cur == NULL) return;
            travesal(cur->left,vec);
            travesal(cur->right,vec);
            vec.push_back(cur->val);
        }
    
        vector<int> preorderTraverasl(TreeNode * root) {
            vector<int> result;
            travelsal(root,result);
            return result;
        }

};

2、用栈实现二叉树遍历

//用栈实现二叉树遍历 
//栈先进后出 队列先进先出
//前序遍历是中左右,每次先处理的是中间节点,那么先将跟节点放入栈中,然后将右孩子加入栈,再加入左孩子。
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); //将结果存在vector容器中
                if(node->right)  st.push_back(node->right); //右  (空节点不如栈)
                if(node->left)   st.push_back(node->left);  //左   
            }
            return result;
        }
};

//中序遍历(迭代法)
//处理:将元素放到result数组中
//遍历节点      指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
//中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点  
class solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        vector<int> result;
        stack<TreeNode*> st;    
        TreeNode* cur =root;   //curr定义为将要入栈的结点,初始化为root
        while(cur != NULL || !st.empty()) {
            if(cur != NULL) {  //指针访问节点,访问到最底层
                st.push(cur);  //将访问的节点放进栈
                cur = cur->left;
            }
            else {
                cur = st.top(); //从栈弹出数据,就是要放进数组的数据  
                st.pop();
                result.push_back(cur->val);  //中
                cur = cur ->right;           //右
            }
        }
        return result;
    }
};

//后序遍历
 if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
 if (node->right) st.push(node->right); // 空节点不入栈  
 reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
        return result;

堆(heap):

删除节点:只能删除堆顶元素,  将最后一个元素喝堆顶元素就行交换,然后重新构造大小顶堆。

1、前K个高频元素

class Solution {
public:
     static bool compare(  pair<string, int>& s1,  pair<string, int>& s2) {
        // 频率相等,按字母排序
        if(s1.second == s2.second) return s1.first < s2.first;
        // 按照频率排序
        else return s1.second > s2.second;
    }
    vector<string> topKFrequent(vector<string>& words, int k) {
        //用哈希表进行查找
        //统计出现频率
        unordered_map<string,int> m; 
        for(string word : words) {
            m[word] ++;
        }
        //将map表放进vector容器中 进行排序
        vector<pair<string,int>> v(m.begin(),m.end());
        sort(v.begin(),v.end(), compare);
        vector<string> ans; //记录输入
        for(int i = 0; i < k; i++ ) {
            ans.push_back(v[i].first);
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值