Leetcode 5281. 使结果不超过阈值的最小除数
又一次参赛,除了第一道Easy题和第二道Medium外,剩下的两道在有限时间内,要么没思路,要么思路不对,超时,要么有思路调试出错,还需多加练习!
(这次的第三题,在循环从1开始,直到找到满足地为止,早就预料到会超时,提交之后果然Time out,切换思路,二分查找,但是有限时间内,没有调试正确!这里做一下笔记,以便学习和提高!)
实际代码记录:
1 #include <iostream> 2 #include <vector> 3 #include <map> 4 #include <algorithm> 5 #include <math.h> 6 7 using namespace std; 8 void init(vector<vector<int> > &vc,int m,int n) 9 { 10 vector<int> level; 11 level.resize(n); 12 vc.resize(m,level); 13 for (int i = 0; i < m; i++) { 14 for (int j = 0; j < n; j++) { 15 cin >> vc[i][j]; 16 } 17 } 18 } 19 20 void printvc(const vector<vector<int> > vc) { 21 for (int i = 0; i < vc.size(); i++) 22 { 23 for (int j = 0; j < vc[0].size(); j++) 24 { 25 cout << vc[i][j] << " "; 26 } 27 cout << endl; 28 } 29 } 30 31 int subtractProductAndSum(int n) { 32 if (n < 10) return 0; 33 int he = 0, ji = 1; 34 int temp; 35 temp = n % 10; 36 while (n) { 37 he += temp; 38 ji *= temp; 39 n = n / 10; 40 temp = n % 10; 41 } 42 cout << "he is " << he << endl; 43 cout << "ji is " << ji << endl; 44 return ji - he; 45 } 46 47 vector<vector<int>> groupThePeople(vector<int>& groupSizes) { 48 vector<vector<int>> res; 49 vector<int> level; 50 vector<int> a; 51 a.resize(groupSizes.size(),0); 52 int count = 0; 53 while(count<groupSizes.size()){ 54 for (int i = 0; i < groupSizes.size(); i++) 55 { 56 if (a[i] == 0) //可用 57 { 58 level.push_back(i); 59 a[i] = 1; 60 count++; 61 if (level.size() != groupSizes[i]) 62 { 63 for (int j = i + 1; j < groupSizes.size(); j++) 64 { 65 if (groupSizes[j] == groupSizes[i] && a[j] == 0) { 66 level.push_back(j); 67 a[j] = 1; 68 count++; 69 if (level.size() == groupSizes[i]) 70 break; 71 } 72 } 73 } 74 75 res.push_back(level); 76 level.clear(); 77 break; 78 } 79 } 80 } 81 82 return res; 83 } 84 85 bool isornot(vector<int> nums, int number, int threshold); 86 int smallestDivisor(vector<int>& nums, int threshold) { 87 //先排序 88 sort(nums.begin(), nums.end()); 89 //然后二分查找一个满足的值 90 int low = 1; 91 int high = nums[nums.size() - 1]; 92 int res=nums[0]; 93 int mid; 94 while (low <= high) { 95 mid = (low + high) / 2; 96 if (!isornot(nums, mid, threshold)) //如果mid不符合,说明,答案在右半个区间,更新low 97 low = mid + 1; 98 else //否则,在左半个区间,更新high 99 { 100 high = mid - 1; 101 res = mid; 102 } 103 } 104 return res; 105 } 106 107 bool isornot(vector<int> nums,int number, int threshold) { 108 int sum = 0; 109 for (int i = 0; i < nums.size(); i++) 110 { 111 sum += ceil(nums[i] / (number*1.0)); 112 //cout<< number<<" sum is "<<sum<<endl; 113 if (sum > threshold) 114 return false; 115 } 116 return true; 117 } 118 int main() 119 { 120 // vector<vector<int> > vc; 121 //init(vc,3,4); 122 //printvc(vc); 123 124 /* 第一题 125 int n; 126 cin >> n; 127 cout << subtractProductAndSum(n) << endl; 128 return 0; 129 */ 130 131 /* 第二题 132 vector<int> a; 133 int n; 134 cin >> n; 135 a.resize(n); 136 for (int i = 0; i < n; i++) 137 { 138 cin >> a[i]; 139 } 140 vector<vector<int>> res; 141 res = groupThePeople(a); 142 for (int j = 0; j < res.size(); j++) 143 { 144 for (int k = 0; k < res[j].size(); k++) 145 { 146 cout << res[j][k] << " "; 147 } 148 cout << endl; 149 } 150 return 0; 151 */ 152 153 /* 154 vector<int> a; 155 int n; 156 cin >> n; 157 int threshold; 158 cin >> threshold; 159 a.resize(n); 160 for (int i = 0; i < n; i++) 161 { 162 cin >> a[i]; 163 } 164 int res = smallestDivisor(a,threshold); 165 cout << res << endl; 166 167 return 0; 168 */ 169 170 return 0; 171 }
第166周赛题目列表:
分析:
第一题很简单,直接提出数字n的每一位,进行求和和求积,然后返回差即可!
第二题是说,每个人站在一个确定人数的分组里,那么,加入这个人在3个人的组group里,group.size()就等于每个人身上的号码。
第三题,就是一开始遍历所有值,但是超时,然后采用二分搜索的方式进行求解:
题目三:
给你一个整数数组 nums 和一个正整数 threshold ,你需要选择一个正整数作为除数,然后将数组里每个数都除以它,并对除法结果求和。
请你找出能够使上述结果小于等于阈值 threshold 的除数中 最小 的那个。
每个数除以除数后都向上取整,比方说 7/3 = 3 , 10/2 = 5 。
题目保证一定有解。
示例 1:
输入:nums = [1,2,5,9], threshold = 6
输出:5
解释:如果除数为 1 ,我们可以得到和为 17 (1+2+5+9)。
如果除数为 4 ,我们可以得到和为 7 (1+1+2+3) 。如果除数为 5 ,和为 5 (1+1+1+2)。
首先写一个函数,判断一个数是否满足数组nums和阈值threshold,
1 bool isornot(vector<int> nums,int number, int threshold) { 2 int sum = 0; 3 for (int i = 0; i < nums.size(); i++) 4 { 5 sum += ceil(nums[i] / (number*1.0)); 6 //cout<< number<<" sum is "<<sum<<endl; 7 if (sum > threshold) 8 return false; 9 } 10 return true; 11 }
然后,数组确定,二分查找这样的最小值即可;
1 int smallestDivisor(vector<int>& nums, int threshold) { 2 //先排序 3 sort(nums.begin(), nums.end()); 4 //然后二分查找一个满足的值 5 int low = 1; 6 int high = nums[nums.size() - 1]; 7 int res=nums[0]; 8 int mid; 9 while (low <= high) { 10 mid = (low + high) / 2; 11 if (!isornot(nums, mid, threshold)) //如果mid不符合,说明,答案在右半个区间,更新low 12 low = mid + 1; 13 else //否则,在左半个区间,更新high 14 { 15 high = mid - 1; 16 res = mid; 17 } 18 } 19 return res; 20 }
题目给定的值,一定满足有解,所以不用考虑无解的情况,因此,low=1,high=max(nums),即当所有的商为1时,最终和最小,一定小于等于阈值;
(很遗憾,当时思路对,但是没有调试出来!)
题目四:
后续补充~~~