华为机试题
共三题,第一题签到题,第二题字符串处理,不是很复杂的那种,第三题将数组分割使得最小值最大。
数组分割使最小值最大:二分最小值,同时check是否有k组大于最小值。题目还要求有多个答案时,第一个分组尽可能地大,如果第一个分组也有多种情况,要使第二个分组尽可能地大,可以贪心处理,从后往前。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int n, k; ll a[500+5]; bool check(ll mid) { int cnt = 0; // 当前划分数 ll sum = 0; // 当前和 for(int i = 0;i < n;i++) { sum += a[i]; if(sum >= mid) { cnt++; sum = 0; if(cnt >= k) return true; } } return false; } int main() { cin >> n >> k; ll low = 0, high = 0, mid; for(int i = 0;i < n;i++) { cin >> a[i]; high += a[i]; } while(low <= high) { cout << low << " " << high << endl; mid = (low + high) >> 1; if(check(mid)) low = mid+1; else high = mid-1; } mid += 2; while(!check(mid)) mid--; printf("mid: %lld\n", mid); vector<int>res; // 记录位置 ll sum = 0; int cnt = 0; for(int i = n-1;i >= 0;i--) { sum += a[i]; if(sum >= mid) { sum = 0; res.push_back(i); cnt++; if(cnt >= k-1) break; } } for(int i = 0;i < n;i++) { printf("%lld%c", a[i], i == n-1 ? '\n' : ' '); if(i+1 == res[res.size()-1]) { printf("/ "); res.pop_back(); } } return 0; }
发现leetcode上也有类似题,leetcode410,分割数组使最小值最大
思路:二分最小值,check(检查如果最小值是mid,分组的个数)
class Solution { public: bool check(vector<int>& nums, int m, long long mid) { int cnt = 1; long long sum = 0; for (int i = 0; i < (int)nums.size(); i++) { if (sum + nums[i] > mid) { sum = nums[i]; cnt++; } else sum += nums[i]; } return cnt <= m; } long long splitArray(vector<int>& nums, int m) { long long low = 0, high = 0, mid = 0; for (int num : nums) { low = max(low, (long long)num); high += num; } while (low < high) { //cout << low << " " << high << endl; mid = (low + high) >> 1; if (check(nums, m, mid)) high = mid; // 保证high是ok的 else low = mid + 1; } //if (check(nums, m, mid - 1)) return mid - 1; //if (check(nums, m, mid)) return mid; return high; } };
个性签名:时间会解决一切