數組中兩元素的最大乘積 | 切割後面積最大的蛋糕 | 重新規劃路線 | 兩個盒子中球的顏色數相同的概率 |
---|---|---|---|
3分 簡單 | 4分 中等 | 5分 中等 | 7分 困難 |
1464 數組中兩元素的最大乘積
解題思路:
其實就是題目就是要求數組中兩個最大的值
維護最大值first_mx,第二大值second_mx
遍歷數組更新這兩值即可
複雜度:
相當於遍歷了一遍nums數組,故爲O(n)
class Solution { public: int maxProduct(vector<int>& nums) { int first_mx=nums[0]; int second_mx=nums[1]; if(first_mx<second_mx) swap(first_mx,second_mx); for(int i=2;i<nums.size();i++){ if(nums[i]>first_mx){ second_mx=first_mx; first_mx=nums[i]; } else{ if(nums[i]>second_mx) second_mx=nums[i]; } } return (first_mx-1)*(second_mx-1); } };
1465 切割後面積最大的蛋糕
解題思路:
先將horizontalCuts,和verticalCuts從小到達排一下
兩個相鄰水平切口的距離就是矩形的高
兩個相鄰豎直切口的距離就是矩形的寬
維護高寬的最大值即可
複雜度:
遍歷都是O(n),最高是從小到大sort的複雜度,最後的複雜度是爲O(nlogn)
const long long mod=1e9+7; class Solution { public: int maxArea(int h, int w, vector<int>& horizontalCuts, vector<int>& verticalCuts) { int len_h=horizontalCuts.size(); int len_v=verticalCuts.size(); sort(horizontalCuts.begin(),horizontalCuts.end()); sort(verticalCuts.begin(),verticalCuts.end()); int a=max(h-horizontalCuts[len_h-1],horizontalCuts[0]),b=max(w-verticalCuts[len_v-1],verticalCuts[0]); for(int i=1;i<horizontalCuts.size();i++){ a=max(a,horizontalCuts[i]-horizontalCuts[i-1]); } for(int i=1;i<verticalCuts.size();i++){ b=max(b,verticalCuts[i]-verticalCuts[i-1]); } long long ans=(long long)a*b%mod; return ans; } };
1466 重新規劃路線
解題思路:
map記錄有向邊,建圖建的是無向圖,從1出發,向兒子節點出發,如果從當前節點到兒子節點的邊是原來的有向邊,說明這邊需要改方向,ans++(ans是最終需要更改的邊的個數)
class Solution { public: int ans=0; vector<int>son[50005]; map<pair<int,int>,int>mp; void dfs(int u,int fa){ for(auto v:son[u]){ if(v==fa) continue; if(mp[make_pair(u,v)]) ans++; dfs(v,u); } } int minReorder(int n, vector<vector<int>>& connections) { ans=0; for(auto it:connections){ mp[make_pair(it[0]+1,it[1]+1)]=1; son[it[0]+1].push_back(it[1]+1); son[it[1]+1].push_back(it[0]+1); } dfs(1,0); return ans; } };
1467 兩個盒子中球的顏色數相同的概率
解題思路:
簡單dp(爲方便處理,房屋、顏色編號都從1開始,可能需要轉化一下)
dp狀態表示放完前i種顏色的球之後,第一個盒子有j個球,共x種顏色,第二個盒子有j個球,共y種顏色 的方案數 dp[i][j][k][x][y] 1)對於第i種球,全加給第一個盒子,或這全加給第二個盒子 dp[i][j][k][x][y]+=dp[i-1][j-t][k][x-1][y]*C[j][t]; 全加給某個盒子,該盒子顏色加1,另一個顏色數不變,該盒子個數加上t 2)對於第i種求,部分加給第一個盒子,部分加給第二個盒子 for(int b=1;b<t;b++) 枚舉加給第一個盒子b個,那麼加給第二個盒子t-b個,此時第一個盒子顏色x加了1,第二個盒子顏色y加了1 dp[i][j][k][x][y]+=dp[i-1][j-b][k-(t-b)][x-1][y-1]*C[j][b]*C[k][t-b]; 本題還涉及到排列的問題,在狀態轉移過程種還需要加上組合數 例如情況1,把t個球加給盒子1,盒子一現在有j個球,那麼這樣的排列有C[j][t]種 也就是說,如果要向一個已經有a個球的盒子裏放入b個數,那麼方案數要乘上 C[a+b][b];
複雜度:
O(n^2 * k^3 * max(ni))
class Solution { long double dp[9][25][25][9][9]; long double C[25][25]; public: double getProbability(vector<int>& balls) { dp[0][0][0][0][0]=1; int n=balls.size(); int sum=0; for(auto it:balls) sum+=it; sum/=2; //C[][]組合數 C[0][0]=1; for (int i=1;i<=sum;++i){ C[i][0]=1; for(int j=1;j<=i;++j) C[i][j]=C[i-1][j]+C[i-1][j-1]; } for(int i=1;i<=n;i++){ int t=balls[i-1]; for(int j=sum;j>=t;j--){ for(int k=0;k<=sum;k++){ for(int x=1;x<=i;x++){ for(int y=0;y<=i;y++){ dp[i][j][k][x][y]+=dp[i-1][j-t][k][x-1][y]*C[j][t]; dp[i][k][j][y][x]+=dp[i-1][k][j-t][y][x-1]*C[j][t]; } } } } for(int b=1;b<t;b++){ for(int j=sum;j>=b;j--){ for(int k=sum;k>=t-b;k--){ for(int x=1;x<=i;x++){ for(int y=1;y<=i;y++){ dp[i][j][k][x][y]+=dp[i-1][j-b][k-(t-b)][x-1][y-1]*C[j][b]*C[k][t-b]; } } } } } } long double ans1=0,ans2=0; for(int i=0;i<=n;i++){ ans1+=dp[n][sum][sum][i][i]; } for(int i=0;i<=n;i++){ for(int j=0;j<=n;j++){ ans2+=dp[n][sum][sum][i][j]; } } ans1=ans1/ans2; return ans1; } };