其他分享
首页 > 其他分享> > 数据结构-学习

数据结构-学习

作者:互联网

数据结构

常用数据结构

数组\字符串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2SfuU4S-1614745156437)(dataStructureAndCpp.assets/image-20201130104101212.png)]

交换字符串首尾, 两个指针

链表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k4DhqZgk-1614745156441)(dataStructureAndCpp.assets/image-20201130104512922.png)]

队列

双端队列

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BNHa1fCN-1614745156444)(dataStructureAndCpp.assets/image-20201214102213947.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ahIHqEGV-1614745156450)(dataStructureAndCpp.assets/image-20201214102436974.png)]

高级数据结构

优先队列

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6e4ZNqBV-1614745156454)(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.assets/image-20201222104319874.png)]

​ 另一个最重要的时间复杂度:优先队列的初始化

前缀树

方法一:暴力搜索法
时间复杂度:O(M*N)
方法二:前缀树
时间复杂度:O(M)

线段树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fd81mVty-1614745156459)(dataStructureAndCpp.assets/image-20201201091550134.png)]

树状数组

也被称为 Binary Indexed Tree

本节课总结

优先队列:常见面试考点,实现过程比较繁琐。在解決面试中的问题时,实行“拿来主义"即可
图:被广泛运用的数据结构,如大数据问题都得运用图论
在社交网络里,每个人可以用图的顶点表示,人与人直接的关系可以用图的边表
在地图上,要求解从起始点到目的地,如何行驶会更快捷,需要运用图论里的最短路径算法
前缀树;出现在面试的难题中,要求能熟练地书写它的实现以及运用
线段树和树状数组:应用场合比较明确
如果要求在一幅图片当中修改像素的颜色,求解任意矩形区间的灰度平均值,则需要采用二维的线段树

排序算法

冒泡排序

原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rcEbIrvw-1614745156462)(dataStructureAndCpp.assets/dc2429f5191b7271678adaeb8d08535f.gif)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xjiwvYmz-1614745156463)(dataStructureAndCpp.assets/image-20201212121353353.png)]

两两比较元素是关键, 怎么知道是否排好序了, 定义一个haschange的变量, 如果该轮比较没有过元素交换, 则证明已经排好序了.

时间复杂度: (n-1) + (n-2) + … + 1 = n*(n-1)/2 --> O(n^2)

空间复杂度:O(1)

插入排序

归并排序

快速排序

图片名称

拓扑排序

有一个学生想要修完5门课程的学分,这5门课程分别用1、2、 5来表示,现在已知学习这些课程有如下的要求:
课程2和4依赖于课程1
课程3依赖于课程2和4
课程4依赖于课程1和2
课程5依赖于课程3和4
那么
这个学生应该按照怎样的顺序来学习这5门课程呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N1Qrqjrj-1614745156465)(dataStructureAndCpp.assets/image-20201214101039363.png)]

堆排序

参考:https://www.cnblogs.com/chengxiao/p/6129630.html

桶排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWAz8sUV-1614745156466)(dataStructureAndCpp.assets/image-20201214103846176.png)]

递归和回溯

递归

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PuHu9272-1614745156468)(dataStructureAndCpp.assets/image-20201214113027078.png)]

回溯

深度与广度优先搜索

深度优先搜索DFS

广度优先搜索BFS

动态规划

将问题逐渐增大或将问题逐渐缩小, 寻找解决方案

线性规划

区间规划

约束规划

二分搜索算法和贪婪

二分搜索

贪婪

高频真题

leetcode3.无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
    请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:

输入: s = ""
输出: 0
#include <iostream>
#include <unordered_set>
#include <algorithm>
using namespace std;

//滑动窗口法, 找到以每个字符开头的最大无重复子串
class Solution {
public:
	int lengthOfLongestSubstring(string s) {
		// 哈希集合,记录每个字符是否出现过
		unordered_set<char> occ;
		int n = s.size();
		// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
		int rk = -1, ans = 0;
		// 枚举左指针的位置,初始值隐性地表示为 -1
		for (int i = 0; i < n; ++i) {
			if (i != 0) {
				// 左指针向右移动一格,移除一个字符
				occ.erase(s[i - 1]);
			}
			while (rk + 1 < n && !occ.count(s[rk + 1])) {
				// 不断地移动右指针
				occ.insert(s[rk + 1]);
				++rk;
			}
			// 第 i 到 rk 个字符是一个极长的无重复字符子串
			ans = max(ans, rk - i + 1);
		}
		return ans;
	}
};

int main()
{
	int rets;
	string s = "abcabcdbb";
	Solution sol;
	rets = sol.lengthOfLongestSubstring(s);
	cout << rets << endl;
	return 0;
}



leetcode4.寻找两个有序数组的中位数

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。

进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:

输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4:

输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5:

输入:nums1 = [2], nums2 = []
输出:2.00000
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

//二分查找
class Solution {
public:
	int getKthElement(const vector<int>& nums1, const vector<int>& nums2, int k) {
		/* 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
		* 这里的 "/" 表示整除
		* nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个
		* nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个
		* 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
		* 这样 pivot 本身最大也只能是第 k-1 小的元素
		* 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
		* 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
		* 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
		*/

		int m = nums1.size();
		int n = nums2.size();
		int index1 = 0, index2 = 0;

		while (true) {
			// 边界情况
			if (index1 == m) {
				return nums2[index2 + k - 1];
			}
			if (index2 == n) {
				return nums1[index1 + k - 1];
			}
			if (k == 1) {
				return min(nums1[index1], nums2[index2]);
			}

			// 正常情况
			int newIndex1 = min(index1 + k / 2 - 1, m - 1);
			int newIndex2 = min(index2 + k / 2 - 1, n - 1);
			int pivot1 = nums1[newIndex1];
			int pivot2 = nums2[newIndex2];
			if (pivot1 <= pivot2) {
				k -= newIndex1 - index1 + 1;
				index1 = newIndex1 + 1;
			}
			else {
				k -= newIndex2 - index2 + 1;
				index2 = newIndex2 + 1;
			}
		}
	}

	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
		int totalLength = nums1.size() + nums2.size();
		if (totalLength % 2 == 1) {
			return getKthElement(nums1, nums2, (totalLength + 1) / 2);
		}
		else {
			return (getKthElement(nums1, nums2, totalLength / 2) + getKthElement(nums1, nums2, totalLength / 2 + 1)) / 2.0;
		}
	}
};

int main()
{
	double rets;
	vector<int> nums1 = { 1, 3 };
	vector<int> nums2 = { 2 };
	Solution sol;
	rets = sol.findMedianSortedArrays(nums1, nums2);
	cout << rets << endl;
	return 0;
}

leetcode23.合并K个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
 1->4->5,
 1->3->4,
 2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:

输入:lists = []
输出:[]
示例 3:

输入:lists = [[]]
输出:[]
//1顺序合并: 以合并2个序列为前提
class Solution {
public:
    ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b;
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                tail->next = bPtr; bPtr = bPtr->next;
            }
            tail = tail->next;
        }
        tail->next = (aPtr ? aPtr : bPtr);
        return head.next;
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *ans = nullptr;
        for (size_t i = 0; i < lists.size(); ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/he-bing-kge-pai-xu-lian-biao-by-leetcode-solutio-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//2.分治法
class Solution {
public:
    ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b;
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                tail->next = bPtr; bPtr = bPtr->next;
            }
            tail = tail->next;
        }
        tail->next = (aPtr ? aPtr : bPtr);
        return head.next;
    }

    ListNode* merge(vector <ListNode*> &lists, int l, int r) {
        if (l == r) return lists[l];
        if (l > r) return nullptr;
        int mid = (l + r) >> 1;
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return merge(lists, 0, lists.size() - 1);
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/he-bing-kge-pai-xu-lian-biao-by-leetcode-solutio-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//3.优先队列: 指针必须要指向一个地方, 初始化的时候必须为其开辟一个地方去指向 new xxx
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
using namespace std;

/**
* 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:
	struct Status {
		int val;
		ListNode *ptr;
		bool operator < (const Status &rhs) const {
			return val > rhs.val;
		}
	};

	priority_queue <Status> q;

	ListNode* mergeKLists(vector<ListNode*>& lists) {
		for (auto node : lists) {
			if (node) q.push({ node->val, node });
		}
		ListNode head, *tail = &head;
		while (!q.empty()) {
			auto f = q.top(); q.pop();
			tail->next = f.ptr;
			tail = tail->next;
			if (f.ptr->next) q.push({ f.ptr->next->val, f.ptr->next });
		}
		return head.next;
	}
};


int main()
{
	vector<ListNode*> lists;
	ListNode* val11 = new ListNode(0);
	ListNode* val12 = new ListNode(0);
	ListNode* val13 = new ListNode(0);
	val11->val = 1;
	val12->val = 4;
	val13->val = 5;
	val11->next = val12;
	val12->next = val13;
	lists.push_back(val11);
	
	vector<int> lis2 = { 3, 4 };
	ListNode* val21 = new ListNode(0);
	val21->val = 1;
	ListNode* cur = val21;
	for (auto lis : lis2)
	{
		ListNode* tmp = new ListNode(0);
		tmp->val = lis;
		cur->next = tmp;
		cur = tmp;
	}
	lists.push_back(val21);

	vector<int> lis3 = { 6 };
	ListNode* val31 = new ListNode(0);
	val31->val = 2;
	ListNode* cur3 = val31;
	for (auto lis : lis3)
	{
		ListNode* tmp = new ListNode(0);
		tmp->val = lis;
		cur3->next = tmp;
		cur3 = tmp;
	}
	lists.push_back(val31);

	ListNode* rets = new ListNode(0);
	Solution sol;
	rets = sol.mergeKLists(lists);
	while (rets){
		cout << rets->val << endl;
		rets = rets->next;
	}
	return 0;
}

leetcode56.合并区间

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Solution {
public:
	vector<vector<int>> merge(vector<vector<int>>& intervals) {
		if (intervals.size() == 0) {
			return{};
		}
		sort(intervals.begin(), intervals.end()); //首先将区间按左端点进行排序
		vector<vector<int>> merged;
		for (int i = 0; i < intervals.size(); ++i) {
			int L = intervals[i][0], R = intervals[i][1];
			if (!merged.size() || merged.back()[1] < L) {
				merged.push_back({ L, R });
			}
			else {
				merged.back()[1] = max(merged.back()[1], R);
			}
		}
		return merged;
	}
};


int main()
{
	vector<vector<int>> intervals = { { 1, 3 }, { 2, 6 }, { 8, 10 }, { 15, 18 } };
	vector<vector<int>> rets;
	Solution sol;
	rets = sol.merge(intervals);
	for (auto ret : rets){
		for (auto r : ret){
			cout << r << " , ";
		}
		cout << endl;
	}
	return 0;
}

leetcode435.无重叠区间

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意:

可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

示例 1:

输入: [ [1,2], [2,3], [3,4], [1,3] ]

输出: 1

解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:

输入: [ [1,2], [1,2], [1,2] ]

输出: 2

解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:

输入: [ [1,2], [2,3] ]

输出: 0

解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


class Solution {
public:
	int eraseOverlapIntervals(vector<vector<int>>& intervals) {
		if (intervals.size() < 2) return 0;
		//首先排序
		sort(intervals.begin(), intervals.end());
		int ret=0;
		int L=0, R=0;
		for (int i = 0; i < intervals.size(); i++){
			if (i == 0){
				L = intervals[i][0];
				R = intervals[i][1];
			}
			else{
				if (intervals[i][0] < R){
					ret = ret + 1;
					R = min(R, intervals[i][1]);
				}
				else
				{
					L = intervals[i][0];
					R = intervals[i][1];
				}
			}
		}
		return ret;
	}
};

int main()
{
	vector<vector<int>> intervals = { {1,2}, { 1,2 }, {1,2 }, { 1,2 } };
	int rets;
	Solution sol;
	rets = sol.eraseOverlapIntervals(intervals);
	cout << rets << endl;
	return 0;
}

leetcode269. 火星字典

现有一种使用字母的全新语言,这门语言的字母顺序与英语顺序不同。
假设,您并不知道其中字母之间的先后顺序。但是,会收到词典中获得一个 不为空的 单词列表。因为是从词典中获得的,所以该单词列表内的单词已经 按这门新语言的字母顺序进行了排序。
您需要根据这个输入的列表,还原出此语言中已知的字母顺序。

示例 1:
输入:
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]
输出: "wertf"

示例 2:
输入:
[
  "z",
  "x"
]
输出: "zx"

示例 3:
输入:
[
  "z",
  "x",
  "z"
] 
输出: "" 
解释: 此顺序是非法的,因此返回 ""。
 
提示:
你可以默认输入的全部都是小写字母
若给定的顺序是不合法的,则返回空字符串即可
若存在多种可能的合法字母顺序,请返回其中任意一种顺序即可

//两大步骤,第一步是根据输入构建一个有向图;第二步是对这个有向图进行拓扑排序。
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<list>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

class Solution {
public:
	// 将当前节点 u 加入到 visited 集合以及 loop 集合中。
	bool topologicalSort(map<char, vector<char>>& adjList, char u, set<char>& visited, set<char>& loop, stack<char>&stk){
		visited.insert(u);
		loop.insert(u);
		if (adjList.count(u)){
			for (int i = 0; i < adjList.at(u).size(); i++){
				char v = adjList.at(u)[i];
				if (loop.count(v)) return false;
				if (!visited.count(v)){
					if (!topologicalSort(adjList, v, visited, loop, stk)){
						return false;
					}
				}
			}
		}
		loop.erase(u);
		stk.push(u);
		return true;
	}
	string alienOrder(vector<string>& words) {
		// 基本情况处理,比如输入为空,或者输入的字符串只有一个
		if (words.size() < 1) return "";
		else if (words.size() == 1) return words[0];

		// 构建有向图:定义一个邻接链表 adjList,也可以用邻接矩阵
		map<char, vector<char>> adjList;
		for (int i = 0; i < words.size()-1; i++){
			string w1 = words[i], w2 = words[i + 1];
			int n1 = w1.size(), n2 = w2.size();
			bool found = false;
			for (int j = 0; j < max(w1.size(), w2.size()); j++){
				char c1 = j < n1 ? w1[j] : NULL;
				char c2 = j < n2 ? w2[j] : NULL;
				if (c1 != NULL && !adjList.count(c1)){
					adjList[c1] = vector<char>();
				}
				if (c2 != NULL && !adjList.count(c2)){
					adjList[c2] = vector<char>();
				}
				if (c1 != NULL && c2 != NULL && c1 != c2 && !found){
					adjList.at(c1).push_back(c2);
					found = true;
				}
			}
		}

		set<char> visited;
		set<char> loop;
		stack<char> stk;
		for (auto items : adjList){
			auto key = items.first;
			if (!visited.count(key)){
				if (!topologicalSort(adjList, key, visited, loop, stk)){
					return "";
				}
			}
		}

		string sb="";
		while (!stk.empty()){
			sb = sb + stk.top();
			stk.pop();
		}
		return sb; 
	}
};

int main()
{
	string rets;
	vector<string> words = { "wrt", "wrf", "er", "ett", "rftt" }; //
	Solution sol;
	rets = sol.alienOrder(words);
	cout << rets << endl;

	return 0;
}

leetcode772.基本计算器

实现一个基本的计算器来计算简单的表达式字符串。
表达式字符串可以包含左括号 (和右括号),加号 + 和减号 -,非负 整数和空格 。
表达式字符串只包含非负整数, +, -, *, / 操作符,左括号 ( ,右括号 )和空格。整数除法需要向下截断。
你可以假定给定的字符串总是有效的。所有的中间结果的范围为 [-2147483648, 2147483647]。

"1 + 1" = 2
" 6-4 / 2 " = 4
"2*(5+5*2)/3+(6/2+8)" = 21
"(2+6* 3+5- (3*14/7+2)*5)+3"=-12
注:不要 使用内置库函数 eval。
#include<iostream>
#include<string>
#include<queue>
#include<ctype.h>
#include<stack>
using namespace std;

class Solution{
public:
	int calculate(string s){
		/*假设只有+和数字的情况*/
		queue<char> q;
		for (auto c : s){
			if (c != ' '){ //允许空格出现
				q.push(c);
			}
		}
		q.push('+');
		return calculate(q);  //拓展允许小括号出现
	}

	int calculate(queue<char>& q){  //&q 使用q的引用

		char sign = '+'; //拓展, 允许'-'出现, sign用于表示数字的正负
		//定义两个变量, num用来表示当前数字
		//sum用来记录最后的和
		int num = 0, sum = 0; 

		//拓展, 有乘除号 , 定义一个新变量stack, 用来记录要被处理的数
		stack<int> stk;

		//遍历队列, 从队列中一个一个取出字符
		while (!q.empty()){
			char c = q.front(); //取出第一个字符
			q.pop();  //取出后删除第一个字符

			//如果当前字符是数字, 那么久更新num变量
			//如果遇到了加号,就把当前num加到sum, num清零
			if (isdigit(c)){
				num = 10 * num + c - '0';
			}
			else if (c == '('){ //遇到左括号, 递归处理, 直到遇到右括号
				num = calculate(q);
			}
			else{
				//遇到了符号
				if (sign == '+') {
					stk.push(num); //遇到加号, 将当前数压入堆栈
				}
				else if (sign == '-'){
					stk.push(-num); //遇到减号, 将当前相反数压入堆栈
				}
				else if (sign == '*'){
					int tmp = stk.top();
					stk.pop();
					stk.push(tmp * num); //乘号
				}
				else if (sign == '/'){
					int tmp = stk.top();
					stk.pop();
					stk.push(tmp / num); //乘号
				}
				num = 0;
				sign = c; //更新sign

				//遇到右括号
				if (c == ')'){
					break;
				}
			}
		}
		
		//将堆栈里的数字加起来
		while (!stk.empty()){
			sum += stk.top();
			stk.pop();
		}
		return sum;

	}
};

int main()
{
	string s = "100*(15  - 5*2 )";
	int rets;
	Solution sol;
	rets = sol.calculate(s);
	cout << rets << endl;
	return 0;
}

leetcode10. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

示例 1:

输入:s = "aa" p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
示例 2:

输入:s = "aa" p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:

输入:s = "ab" p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:

输入:s = "aab" p = "c*a*b"
输出:true
解释:因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:

输入:s = "mississippi" p = "mis*is*p*."
输出:false

leetcode44.通配符匹配

给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。

‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。

说明:

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:

输入:
s = "aa"
p = "*"
输出: true
解释: '*' 可以匹配任意字符串。
示例 3:

输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
示例 4:

输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".
示例 5:

输入:
s = "acdcb"
p = "a*c?b"
输出: false

leetcode84.柱状图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例:

输入: [2,1,5,6,2,3]
输出: 10

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NgPDUkjN-1614745156494)(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.assets/image-20210111113415359.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ijJjgIT-1614745156495)(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.assets/image-20210111113432564.png)]

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

class Solution {
public:
	int largestRectangleArea(vector<int>& heights) {
		int n = heights.size(), maxarea = 0;
		stack<int> stk;
		for (int i = 0; i <= n; i++){
			while (!stk.empty() && (i == n || heights[i] < heights[stk.top()])){
				int height = heights[stk.top()];
				int width = stk.empty() ? i : i - stk.top();
				maxarea = max(maxarea, width*height);
				stk.pop();
			}
			stk.push(i);
		}
		return maxarea;
	}
};

int main()
{
	vector <int> heights = { 2, 1, 5, 6, 5, 3 };
	int rets;
	Solution sol;
	rets = sol.largestRectangleArea(heights);
	cout << rets << endl;
	return 0;
}

leetcode28.实现strStr()

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2
示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

#include
using namespace std;

class Solution {
public:
vector getLPS(string str){
//初始化一个lps容器保存最终结果
vector lps(str.size(),0);
// lps 的第一个值一定是 0,
//即长度为 1 的字符串的最长公共前缀后缀的长度为 0,直接从第二个位置遍历。
//并且,初始化当前最长的 lps 长度为 0,用 len 变量记录下
int i = 1, len = 0;
//指针i遍历整个输入字符串
while (i < str.size()){
//若 i 指针能延续前缀和后缀,则更新 lps 值为 len+1
if (str[i] == str[len]) { lps[i++] = ++len; }
//否则,判断 len 是否大于 0,尝试第二长的前缀和后缀,是否能继续延续下去
else if (len>0) { len = lps[len - 1]; }
else { i++; }
}
return lps;
}
int strStr(string haystack, string needle) {
/KMP法/
int m = haystack.size();
int n = needle.size();
if (n == 0) return 0;
vector lps= getLPS(needle);
int i = 0, j = 0;
while (i < m){
if (haystack[i] == needle[j]){
i++;
j++;
}
else if (j == n){
return i - n;
}
else if (j>0){
j = lps[j - 1];
}
else{
i++;
}
}
return -1;
}

};

int main()
{
string haystack = “hello”;
string needle = “ll”;
int rets;
Solution sol;
rets = sol.strStr(haystack, needle);
cout << rets << endl;
return 0;
}



## leetcode336.回文对

给定一组 **互不相同** 的单词, 找出所有**不同** 的索引对`(i, j)`,使得列表中的两个单词, `words[i] + words[j]` ,可拼接成回文串。

示例 1:

输入:[“abcd”,“dcba”,“lls”,“s”,“sssll”]
输出:[[0,1],[1,0],[3,2],[2,4]]
解释:可拼接成的回文串为 [“dcbaabcd”,“abcddcba”,“slls”,“llssssll”]
示例 2:

输入:[“bat”,“tab”,“cat”]
输出:[[0,1],[1,0]]
解释:可拼接成的回文串为 [“battab”,“tabbat”]


- 解题思路

  - 回文:正读和反读都一样的字符串

  - 检查字符串是否回文

    - 翻转给定字符串后,对比原字符串,
       需 要O(n)的空间复杂度

    -  定义指针主指向字符串的头,定义指针j指向字符串的尾,
       从两头开始检查,发现不相等表明不是回文,
       直检查到两个指针相遇为止

      ```c++
      //判断回文对
      bool isPalindrome(string word){
      	int i = 0;
      	int j = word.size() - 1;
      	while (i < j){
      		if (word[i++] != word[j--]){
      			return false;
      		}
      	}
      	return true;
      }
      ```

- 暴力法

  ```c++
  #include <iostream>
  #include <string>
  #include <vector>
  #include <map>
  #include <unordered_map>
  using namespace std;
  
  
  
  class Solution {
  public:
  	//判断回文对
  	bool isPalindrome(string word){
  		int i = 0;
  		int j = word.size() - 1;
  		while (i < j){
  			if (word[i++] != word[j--]){
  				return false;
  			}
  		}
  		return true;
  	}
  
  	vector<vector<int>> palindromePairs(vector<string>& words) {
  		/*暴力法*/
  		vector<vector<int>> rets;
  		int m = words.size();
  		for (int i = 0; i < m; i++){
  			for (int j = i + 1; j < m; j++){
  				if (isPalindrome(words[i] + words[j])){
  					vector<int> temp = { i, j };
  					rets.push_back(temp);
  				}
  				if (isPalindrome(words[j] + words[i])){
  					vector<int> temp = { j, i };
  					rets.push_back(temp);
  				}
  			}
  		}
  		return rets;
  	}
  };
  
  
  
  int main()
  {
  	vector<string> words = { "bat", "tab", "cat" };
  
  	vector<vector<int>>  rets;
  	
  	Solution sol;
  	rets = sol.palindromePairs(words);
  	for (auto ret : rets){
  		cout << ret[0] << " , " << ret[1] << endl;
  	}
  	return 0;
  }
  

leetcode340.至多包含K个不同字符的最长子串

给定一个字符串 *s* ,找出 至多 包含 k 个不同字符的最长子串 *T*

示例 1:

输入: s = "eceba", k = 2
输出: 3
解释: 则 T 为 "ece",所以长度为 3。
示例 2:

输入: s = "aa", k = 1
输出: 2
解释: 则 T 为 "aa",所以长度为 2。

leetcode407.接雨水

给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。

示例:

给出如下 3x6 的高度图:
[
  [1,4,3,1,3,2],
  [3,2,1,3,2,4],
  [2,3,3,2,3,1]
]

返回 4 。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dpiqrjAn-1614745156496)(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.assets/image-20210112145844597.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfxYrr31-1614745156498)(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.assets/image-20210112145901498.png)]

leetcode417.太平洋大西洋水流问题

冲刺

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LAPtGqi5-1614745156499)(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.assets/image-20210112151603057.png)]

leetcode336.回文对

给定一组 互不相同 的单词, 找出所有不同 的索引对(i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。

示例 1:

输入:["abcd","dcba","lls","s","sssll"]
输出:[[0,1],[1,0],[3,2],[2,4]] 
解释:可拼接成的回文串为 ["dcbaabcd","abcddcba","slls","llssssll"]
示例 2:

输入:["bat","tab","cat"]
输出:[[0,1],[1,0]] 
解释:可拼接成的回文串为 ["battab","tabbat"]

leetcode340.至多包含K个不同字符的最长子串

给定一个字符串 *s* ,找出 至多 包含 k 个不同字符的最长子串 *T*

示例 1:

输入: s = "eceba", k = 2
输出: 3
解释: 则 T 为 "ece",所以长度为 3。
示例 2:

输入: s = "aa", k = 1
输出: 2
解释: 则 T 为 "aa",所以长度为 2。

leetcode407.接雨水

给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。

示例:

给出如下 3x6 的高度图:
[
  [1,4,3,1,3,2],
  [3,2,1,3,2,4],
  [2,3,3,2,3,1]
]

返回 4 。

[外链图片转存中…(img-dpiqrjAn-1614745156496)]

[外链图片转存中…(img-UfxYrr31-1614745156498)]

leetcode417.太平洋大西洋水流问题

冲刺

[外链图片转存中…(img-LAPtGqi5-1614745156499)]

标签:rets,include,return,nums,int,学习,vector,数据结构
来源: https://blog.csdn.net/jonado13/article/details/114306901