寫在前面
昨晚的雙週賽有丶水,我居然全做出來了,總結一下昨天的題目,應該就是這個表情:
雙週賽 23
5360. 統計最大組的數目
給你一個整數 n 。請你先求出從 1 到 n 的每個整數 10 進製表示下的數位和(每一位上的數字相加),然後把數位和相等的數字放到同一個組中。
請你統計每個組中的數字數目,並返回數字數目並列最多的組有多少個。
示例 1:
輸入:n = 13
輸出:4
解釋:總共有 9 個組,將 1 到 13 按數位求和後這些組分別是:
[1,10],[2,11],[3,12],[4,13],[5],[6],[7],[8],[9]。總共有 4 個組擁有的數字並列最多。
解法:
遍歷求和,然後用哈希表統計和的個數,然後統計最大次數的出現次數。
代碼:
class Solution {
public:
int countLargestGroup(int n) {
vector<int> a(10001,0);
int mm = 0;
for(int i=1; i<=n; i++){
int t = i;
int s = 0;
while(t>0){
s += t % 10;
t/=10;
}
mm = max(s,mm);//最大和就是哈希表的範圍
++a[s];
}
int m = 0;
for(int i=1; i<=mm; ++i){//尋找出現最多的次數
m = max(m,a[i]);
}
int res = 0;
for(int i=1; i<=mm; ++i)//統計該最大次數的出現次數
if(a[i]==m) ++res;
return res;
}
};
5362. 構造 K 個迴文字符串
給你一個字符串 s 和一個整數 k 。請你用 s 字符串中 所有字符 構造 k 個非空 迴文串 。
如果你可以用 s 中所有字符構造 k 個迴文字符串,那麼請你返回 True ,否則返回 False 。
示例 1:
輸入:s = “annabelle”, k = 2
輸出:true
解釋:可以用 s 中所有字符構造 2 個迴文字符串。
一些可行的構造方案包括:“anna” + “elble”,“anbna” + “elle”,“anellena” + “b”
解法:
統計每個字母出現的個數,然後再統計個數是奇數的字母個數,通過迴文字符串的特性可以知道,一個迴文字符串最多有一個出現次數爲奇數的字母,所以如果奇數的字母個數大於k,那麼就一定不能構造。
代碼:
class Solution {
public:
bool canConstruct(string s, int k) {
vector<int> a(30,0);
if(k>s.length()) return false;
for(int i=0; i<s.length(); ++i){
++a[int(s[i]-'a')];
}
int c = 0;
for(int i=0; i<30; ++i){
if(a[i]%2==1)
++c;
}
if(c>k) return false;
return true;
}
};
5361. 圓和矩形是否有重疊
給你一個以 (radius, x_center, y_center) 表示的圓和一個與座標軸平行的矩形 (x1, y1, x2, y2),其中 (x1, y1) 是矩形左下角的座標,(x2, y2) 是右上角的座標。
如果圓和矩形有重疊的部分,請你返回 True ,否則返回 False 。
換句話說,請你檢測是否 存在 點 (xi, yi) ,它既在圓上也在矩形上(兩者都包括點落在邊界上的情況)。
解法:
邊界判斷
比賽的時候沒有去想數學法,直接畫圖找矩形和圓的位置關係了,但是因爲條件考慮的不全,wa了4次才過。
代碼:
class Solution {
public:
bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
int circleleft = x_center - radius;
int circleright = x_center + radius;
int circletop = y_center + radius;
int circlebot = y_center - radius;
if(circletop<y1) return false;
if(circlebot>y2) return false;
if(circleleft>x2) return false;
if(circleright<x1) return false;
if(circletop<=y2 && circlebot>=y1 && circleleft>=x1 && circleright<=x2) return true;
if(circletop>=y2 && circlebot<=y1 && circleleft<=x1 && circleright>=x2) return true;
if(circleright==x1 || circleright==x2) return true;
if(circleleft==x2 || circleleft==x1) return true;
if(circlebot==y2 || circlebot==y1) return true;
if(circletop==y1 || circletop==y2) return true;
if(circleleft>x1 && circleright<x2) return true;
if(circlebot>y1 && circletop<y2) return true;
int d1 = (x1-x_center)*(x1-x_center) + (y1-y_center)*(y1-y_center);
int d2 = (x1-x_center)*(x1-x_center) + (y2-y_center)*(y2-y_center);
int d3 = (x2-x_center)*(x2-x_center) + (y1-y_center)*(y1-y_center);
int d4 = (x2-x_center)*(x2-x_center) + (y2-y_center)*(y2-y_center);
int r = radius * radius;
if(r<d1 && r<d2 && r<d3 && r<d4) return false;
if(r>d1 && r>d2 && r>d3 && r>d4) return false;
return true;
}
};
數學法
用圓心到矩陣中心距離減去矩陣中心到矩陣一角的距離,跟半徑比較。
代碼:
class Solution {
public:
bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
int x=(x1+x2)/2,y=(y1+y2)/2;
double s=distance(x,y,x_center,y_center);
double s1=distance(x,y,x1,y1);
if(radius>=int(s-s1)) return true;
return false;
}
double distance(int a,int b,int c,int d){
double s;
s=sqrt((a-c)*(a-c)+(b-d)*(b-d));
return s;
}
};
5363. 做菜順序
一個廚師收集了他 n 道菜的滿意程度 satisfaction ,這個廚師做出每道菜的時間都是 1 單位時間。
一道菜的 「喜愛時間」係數定義爲烹飪這道菜以及之前每道菜所花費的時間乘以這道菜的滿意程度,也就是 time[i]*satisfaction[i] 。
請你返回做完所有菜 「喜愛時間」總和的最大值爲多少。
你可以按 任意 順序安排做菜的順序,你也可以選擇放棄做某些菜來獲得更大的總和。
示例 1:
輸入:satisfaction = [-1,-8,0,5,-9]
輸出:14
解釋:去掉第二道和最後一道菜,最大的喜愛時間係數和爲 (-11 + 02 + 5*3 = 14) 。每道菜都需要花費 1 單位時間完成。
提示:
- n == satisfaction.length
- 1 <= n <= 500
- -10^3 <= satisfaction[i] <= 10^3
解法:
數據範圍小的嚇人,這題貪心就行了。
先排序,根據喜愛時間的定義,我們要把滿意度大的菜放到後面,然後從第一個點開始作爲做菜起來,然後起點往後移動,因爲數據範圍很小,也不需要優化了,每次求出喜愛時間求出最大值就行了。
代碼:
class Solution {
public:
int maxSatisfaction(vector<int>& a) {
if(a.empty()) return 0;
sort(a.begin(),a.end());//排序
int p = 0;//起點位置
int res = 0;
while(p<a.size()){
int sat = 0;
for(int i=p; i<a.size(); ++i){
sat += (i-p+1) * a[i];
}
res = max(sat,res);
++p;
}
return res;
}
};