- 剑指 Offer 61. 扑克牌中的顺子(重点)">剑指 Offer 61. 扑克牌中的顺子(重点)
- 剑指 Offer 45. 把数组排成最小的数(必看)">剑指 Offer 45. 把数组排成最小的数(必看)
- 剑指 Offer 40. 最小的k个数(大顶堆/优先队列)">剑指 Offer 40. 最小的k个数(大顶堆/优先队列)
- 剑指 Offer 41. 数据流中的中位数(大顶堆与小顶堆/优先队列)">剑指 Offer 41. 数据流中的中位数(大顶堆与小顶堆/优先队列)
剑指 Offer 61. 扑克牌中的顺子(重点)
感觉剑指offer里面的排序题都好难。这一题的关键在于要看出来总共就五张牌,除0外重复的不行,最大值与最小值之差小于5。满足这两个条件即可
class Solution {
public:
bool isStraight(vector<int>& nums) {
int maxs = 0, mins = 0, jok = 0;
sort(nums.begin(), nums.end());
for(int i = 0; i < 4; i++){
if(nums[i] == 0) jok++;
if(nums[i]!=0&&nums[i] == nums[i+1]) return false;
}
return (nums[4] - nums[jok]) < 5;
}
};
剑指 Offer 45. 把数组排成最小的数(必看)
这一题也有点类似脑筋急转弯。总结的就是几句话
- 如果x比y小,想要两个拼接起来最小,只能是x在前面。
- 因为在c++里面比较两个字符串的大小,是从首字母开始比的,如果首字母出了结果。后面的就都不会管了
总结就是,直接to_string之后无脑排序然后拼接就行了。
快排写法
class Solution { public: string minNumber(vector<int>& nums) { vector<string> strs; for(int i = 0; i < nums.size(); i++) strs.push_back(to_string(nums[i])); quickSort(strs, 0, strs.size() - 1); string res; for(string s : strs) res.append(s); return res; } private: void quickSort(vector<string>& strs, int l, int r) { if(l >= r) return; int i = l, j = r; while(i < j) { while(strs[j] + strs[l] >= strs[l] + strs[j] && i < j) j--; while(strs[i] + strs[l] <= strs[l] + strs[i] && i < j) i++; swap(strs[i], strs[j]); } swap(strs[i], strs[l]); quickSort(strs, l, i - 1); quickSort(strs, i + 1, r); } };
sort写法
class Solution { public: string minNumber(vector<int>& nums) { vector<string> strs; string res; for(int i = 0; i < nums.size(); i++) strs.push_back(to_string(nums[i])); sort(strs.begin(), strs.end(), [](string& x, string& y){ return x + y < y + x; }); for(int i = 0; i < strs.size(); i++) res.append(strs[i]); return res; } };
剑指 Offer 40. 最小的k个数(大顶堆/优先队列)
这一题如果直接sort然后取,虽然能过,但是面试官不喜欢看到这样的答案。所以应该使用大顶堆的方法来一直维护四个最小值。
class Solution { public: vector<int> getLeastNumbers(vector<int>& arr, int k) { vector<int> vec(k, 0); if (k == 0) { // 排除 0 的情况 return vec; } priority_queue<int> Q;//依靠堆来实现优先队列 for (int i = 0; i < k; ++i) { Q.push(arr[i]); } for (int i = k; i < (int)arr.size(); ++i) { if (Q.top() > arr[i]) { Q.pop(); Q.push(arr[i]); } } for (int i = 0; i < k; ++i) { vec[i] = Q.top(); Q.pop(); } return vec; } };
剑指 Offer 41. 数据流中的中位数(大顶堆与小顶堆/优先队列)
这一题使用了c++优先队列的内置参数,直接定义了大顶堆与小顶堆。一个存最大值,一个存最小值。
less大顶堆
greater小顶堆
注意始终保证大顶堆的最大值小于或等于右边堆的最小值。class MedianFinder { public: // 最大堆,存储左边一半的数据,堆顶为最大值 priority_queue<int, vector<int>, less<int>> maxHeap;//大顶堆 // 最小堆, 存储右边一半的数据,堆顶为最小值 priority_queue<int, vector<int>, greater<int>> minHeap;//小顶堆 /** initialize your data structure here. */ MedianFinder() { } // 维持堆数据平衡,并保证左边堆的最大值小于或等于右边堆的最小值 void addNum(int num) { /* * 当两堆的数据个数相等时候,左边堆添加元素。 * 采用的方法不是直接将数据插入左边堆,而是将数据先插入右边堆,算法调整后 * 将堆顶的数据插入到左边堆,这样保证左边堆插入的元素始终是右边堆的最小值。 * 同理左边数据多,往右边堆添加数据的时候,先将数据放入左边堆,选出最大值放到右边堆中。 */ if (maxHeap.size() == minHeap.size()) { minHeap.push(num); int top = minHeap.top(); minHeap.pop(); maxHeap.push(top); } else { maxHeap.push(num); int top = maxHeap.top(); maxHeap.pop(); minHeap.push(top); } } double findMedian() { if (maxHeap.size() == minHeap.size()) { return (maxHeap.top()+minHeap.top())*1.0/2; } else { return maxHeap.top()*1.0; } } };