学习链接:
1. 在排序数组中查找元素的第一个和最后一个位置
题目来源:在排序数组中查找元素的第一个和最后一个位置
题解:
//解法1
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==target){
right=mid-1;
}
else if(nums[mid]<target){
left=mid+1;
}
else if(nums[mid]>target){
right=mid-1;
}
}
if(left==nums.size()) return vector<int>{-1,-1};
int left2=0,right2=nums.size()-1;
while(left2<=right2){
int mid2=left2+(right2-left2)/2;
if(nums[mid2]==target){
left2=mid2+1;
}
else if(nums[mid2]<target){
left2=mid2+1;
}
else if(nums[mid2]>target){
right2=mid2-1;
}
}
if(left2<1) return vector<int>{-1,-1};
return (nums[left]==target&&nums[left2-1]==target)?vector<int>{left,right2}:vector<int>{-1,-1};
}
};
//官方解法
class Solution {
public:
int binarySearch(vector<int>& nums, int target, bool lower) {
int left = 0, right = (int)nums.size() - 1, ans = (int)nums.size();
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] > target || (lower && nums[mid] >= target)) {
right = mid - 1;
ans = mid;
} else {
left = mid + 1;
}
}
return ans;
}
vector<int> searchRange(vector<int>& nums, int target) {
int leftIdx = binarySearch(nums, target, true);
int rightIdx = binarySearch(nums, target, false) - 1;
if (leftIdx <= rightIdx && rightIdx < nums.size() && nums[leftIdx] == target && nums[rightIdx] == target) {
return vector<int>{leftIdx, rightIdx};
}
return vector<int>{-1, -1};
}
};
2. 按权重生成随机数
题目来源:剑指 Offer II 071. 按权重生成随机数
题解:
class Solution {
public:
vector<int> prefix;
int total = 0;
Solution(vector<int>& w) {
prefix.push_back(0);
for(int i = 0; i < w.size(); i++){
total += w[i];
prefix.push_back(total);//填充前缀和数组
}
srand((unsigned)time(NULL));//设置随机数种子
}
int pickIndex() {
int random = (rand()%(total - 1 + 1)) + 1;//生成闭区间[1,total]范围内的一个随机数
return find(random);//调用二分查找加速
}
int find(int target){
int l = 0;
int r = prefix.size() - 1;
while(l <= r){
int mid = (l + r) >> 1;
if(prefix[mid] == target) return mid - 1;
else if(prefix[mid] < target) l = mid + 1;
else r = mid - 1;
}
return l - 1;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(w);
* int param_1 = obj->pickIndex();
*/
3. 在D天内送达包裹的能力
题目来源:1011. 在 D 天内送达包裹的能力
知识点:【STL】
- max_element()
- accumulate()
题解:
class Solution {
public:
int shipWithinDays(vector<int>& weights, int days) {
int left=*max_element(weights.begin(),weights.end());
int right=accumulate(weights.begin(),weights.end(),0);
while(left<right){
int mid=left+(right-left)/2;
int need=1,cur=0;
for(int weight:weights){
if(cur+weight>mid){
need++;
cur=0;
}
cur+=weight;
}
if(need<=days){
right=mid;
}
else
left=mid+1;
}
return left;
}
};
4.分割数组的最大值
题目来源:410. 分割数组的最大值
题解:
class Solution {
public:
bool check(vector<int>& nums, int x, int m) {
long long sum = 0;
int cnt = 1;
for (int i = 0; i < nums.size(); i++) {
if (sum + nums[i] > x) {
cnt++;
sum = nums[i];
} else {
sum += nums[i];
}
}
return cnt <= m;
}
int splitArray(vector<int>& nums, int k) {
long long left=*max_element(nums.begin(),nums.end());
long long right=accumulate(nums.begin(),nums.end(),0);
while(left<right){
long long mid=left+(right-left)/2;
if(check(nums,mid,k))
right=mid;
else
left=mid+1;
}
return left;
}
};
5.田忌赛马
int[] advantageCount(int[] nums1, int[] nums2) {
int n = nums1.length;
// 给 nums2 降序排序
PriorityQueue<int[]> maxpq = new PriorityQueue<>(
(int[] pair1, int[] pair2) -> {
return pair2[1] - pair1[1];
}
);
for (int i = 0; i < n; i++) {
maxpq.offer(new int[]{i, nums2[i]});
}
// 给 nums1 升序排序
Arrays.sort(nums1);
// nums1[left] 是最小值,nums1[right] 是最大值
int left = 0, right = n - 1;
int[] res = new int[n];
while (!maxpq.isEmpty()) {
int[] pair = maxpq.poll();
// maxval 是 nums2 中的最大值,i 是对应索引
int i = pair[0], maxval = pair[1];
if (maxval < nums1[right]) {
// 如果 nums1[right] 能胜过 maxval,那就自己上
res[i] = nums1[right];
right--;
} else {
// 否则用最小值混一下,养精蓄锐
res[i] = nums1[left];
left++;
}
}
return res;
}
6.优势洗牌【不太懂捏】
题目来源:870. 优势洗牌
题解:
class Solution {
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size(),ids[n];
vector<int> ans(n);
sort(nums1.begin(),nums1.end());
iota(ids,ids+n,0);
sort(ids, ids + n, [&](int i, int j) { return nums2[i] < nums2[j]; });
int left=0,right=n-1;
for(int x:nums1){
ans[x>nums2[ids[left]]?ids[left++]:ids[right--]]=x;
}
return ans;
}
};
7.O(1) 时间插入、删除和获取随机元素
题目来源:380. O(1) 时间插入、删除和获取随机元素
题解:
class RandomizedSet {
public:
vector<int> nums;
unordered_map<int,int> idx;
RandomizedSet() {
}
bool insert(int val) {
if(idx.count(val))
return false;
idx[val]=nums.size();
nums.push_back(val);
return true;
}
bool remove(int val) {
if(idx.count(val)){
int index=idx[val];
idx[nums.back()]=index;
swap(nums[index],nums.back());
nums.pop_back();
idx.erase(val);
return true;
}
else
return false;
}
int getRandom() {
return nums[rand()%nums.size()];
}
};
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/