1. 程式人生 > 實用技巧 >LeetCode 第 196 場周賽 (題目:5452-5455,這是參加過最坑的周賽,暴力n^2居然可以過)

LeetCode 第 196 場周賽 (題目:5452-5455,這是參加過最坑的周賽,暴力n^2居然可以過)

5452. 判斷能否形成等差數列

給你一個數字陣列arr

如果一個數列中,任意相鄰兩項的差總等於同一個常數,那麼這個數列就稱為等差數列。

如果可以重新排列陣列形成等差數列,請返回true;否則,返回false

示例 1:

輸入:arr = [3,5,1]
輸出:true
解釋:對陣列重新排序得到 [1,3,5] 或者 [5,3,1] ,任意相鄰兩項的差分別為 2 或 -2 ,可以形成等差數列。

示例 2:

輸入:arr = [1,2,4]
輸出:false
解釋:無法通過重新排序得到等差數列。

提示:

  • 2 <= arr.length <= 1000
  • -10^6 <= arr[i] <= 10^6
class Solution {
public boolean canMakeArithmeticProgression(int[] arr) {
Arrays.sort(arr);
int temp = arr[1]-arr[0];
for (int i=1;i<arr.length;i++){
if(temp!=arr[i]-arr[i-1]){
return false;
}
}
return true;
}
}

5453. 所有螞蟻掉下來前的最後一刻

有一塊木板,長度為n個單位。一些螞蟻在木板上移動,每隻螞蟻都以每秒一個單位的速度移動。其中,一部分螞蟻向左移動,其他螞蟻向右移動。

當兩隻向不同方向移動的螞蟻在某個點相遇時,它們會同時改變移動方向並繼續移動。假設更改方向不會花費任何額外時間。

而當螞蟻在某一時刻t到達木板的一端時,它立即從木板上掉下來。

給你一個整數n和兩個整數陣列left以及right。兩個陣列分別標識向左或者向右移動的螞蟻在t = 0時的位置。請你返回最後一隻螞蟻從木板上掉下來的時刻。

示例 1:

輸入:n = 4, left = [4,3], right = [0,1]
輸出:4
解釋:如上圖所示:
-下標 0 處的螞蟻命名為 A 並向右移動。
-下標 1 處的螞蟻命名為 B 並向右移動。
-下標 3 處的螞蟻命名為 C 並向左移動。
-下標 4 處的螞蟻命名為 D 並向左移動。
請注意,螞蟻在木板上的最後時刻是 t = 4 秒,之後螞蟻立即從木板上掉下來。(也就是說在 t = 4.0000000001 時,木板上沒有螞蟻)。

示例 2:

輸入:n = 7, left = [], right = [0,1,2,3,4,5,6,7]
輸出:7
解釋:所有螞蟻都向右移動,下標為 0 的螞蟻需要 7 秒才能從木板上掉落。

示例 3:

輸入:n = 7, left = [0,1,2,3,4,5,6,7], right = []
輸出:7
解釋:所有螞蟻都向左移動,下標為 7 的螞蟻需要 7 秒才能從木板上掉落。

示例 4:

輸入:n = 9, left = [5], right = [4]
輸出:5
解釋:t = 1 秒時,兩隻螞蟻將回到初始位置,但移動方向與之前相反。

示例 5:

輸入:n = 6, left = [6], right = [0]
輸出:6

提示:

  • 1 <= n <= 10^4
  • 0 <= left.length <= n + 1
  • 0 <= left[i] <= n
  • 0 <= right.length <= n + 1
  • 0 <= right[i] <= n
  • 1 <= left.length + right.length <= n + 1
  • leftright中的所有值都是唯一的,並且每個值只能出現在二者之一中。

PS:

這個題的話,其實想明白了就很簡單,兩隻螞蟻相撞,就各取反方向,

螞蟻那麼小,我們可以看成,兩隻螞蟻互相穿過去了

class Solution {
public int getLastMoment(int n, int[] left, int[] right) {
int l=-100000,r=-100000;
int ll=0,rr=100000;
//面向左面的想要下去,只能是向左走,他們最大的那個就是距離0最遠的點,相差的距離就是最長的時間
for(int i:left){
ll=Math.max(ll,i);
}
//反之 面向右面就要向右走,距離n最遠的點的距離就是最長時間,這裡面向右面的要取最小值
for(int i:right){
rr=Math.min(rr,i);
}
//防止有空陣列出現
if(left.length!=0)
l = ll;
if(right.length!=0)
r = n-rr;
return Math.max(l,r);
}
}

5454. 統計全 1 子矩形

給你一個只包含 0 和 1 的rows * columns矩陣mat,請你返回有多少個子矩形的元素全部都是 1 。

示例 1:

輸入:mat = [[1,0,1],
[1,1,0],
[1,1,0]]
輸出:13
解釋:
有 6個 1x1 的矩形。
有 2 個 1x2 的矩形。
有 3 個 2x1 的矩形。
有 1 個 2x2 的矩形。
有 1 個 3x1 的矩形。
矩形數目總共 = 6 + 2 + 3 + 1 + 1 = 13。

示例 2:

輸入:mat = [[0,1,1,0],
[0,1,1,1],
[1,1,1,0]]
輸出:24
解釋:
有 8 個 1x1 的子矩形。
有 5 個 1x2 的子矩形。
有 2 個 1x3 的子矩形。
有 4 個 2x1 的子矩形。
有 2 個 2x2 的子矩形。
有 2 個 3x1 的子矩形。
有 1 個 3x2 的子矩形。
矩形數目總共 = 8 + 5 + 2 + 4 + 2 + 2 + 1 = 24 。

示例 3:

輸入:mat = [[1,1,1,1,1,1]]
輸出:21

示例 4:

輸入:mat = [[1,0,1],[0,1,0],[1,0,1]]
輸出:5

提示:

  • 1 <= rows<= 150
  • 1 <= columns<= 150
  • 0 <= mat[i][j] <= 1

PS:

這裡有一份大哥的暴力大法,我還有一份程式碼,先不寫註釋了,等下面有時間再加上註釋吧

/*暴力法通過
@v7fgg
執行用時:285 ms, 在所有 Java 提交中擊敗了100.00%的使用者
記憶體消耗:40.9 MB, 在所有 Java 提交中擊敗了100.00%的使用者
2020年7月5日 13:13
*/
class Solution {
public int numSubmat(int[][] mat) {
int ans=0;
int m=mat.length;
int n=mat[0].length;
//ij確定左上角,kl確定右下角
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
for(int k=i;k<m;k++){
for(int l=j;l<n;l++){
//逐個檢查
boolean bukeyi=false;//表示此矩形是不是全1
for(int a=i;a<=k;a++){
for(int b=j;b<=l;b++){
if(mat[a][b]==0){
bukeyi=true;
break;
}
}
if(bukeyi){break;}
}
if(bukeyi){break;}
ans++;
}
}
}
}
return ans;
}
}
class Solution {
public int numSubmat(int[][] mat) {
int[][] a = new int[mat.length+1][mat[0].length+1];
for(int i=1;i<=mat.length;i++){
for(int j=1;j<=mat[i-1].length;j++){
if( mat[i-1][j-1]==1 ) a[i][j] = a[i-1][j] + 1;
else a[i][j] = 0;
}
}
// for(int i=1;i<=mat.length;i++){
// for(int j=1;j<=mat[i-1].length;j++){
// System.out.print(a[i][j]+" ");
// }
// System.out.println();
// }
int[] Stk = new int[mat.length+5];
int top = 0;
int ans = 0,count=0;
for(int i=1;i<=mat.length;i++){
top =0; count = 0;
for(int j=1;j<=mat[0].length;j++){
count += a[i][j];
while( top>0 && a[i][j] <= a[i][Stk[top]] ) {
count -= ( Stk[top] - Stk[top-1] ) * ( a[i][Stk[top]] - a[i][j] );
top--;
}
ans += count;
Stk[++top] = j;
}
}
return ans;
}
}

5455. 最多 K 次交換相鄰數位後得到的最小整數

給你一個字串num和一個整數k。其中,num表示一個很大的整數,字串中的每個字元依次對應整數上的各個數位。

你可以交換這個整數相鄰數位的數字最多k次。

請你返回你能得到的最小整數,並以字串形式返回。

示例 1:

輸入:num = "4321", k = 4
輸出:"1342"
解釋:4321 通過 4 次交換相鄰數位得到最小整數的步驟如上圖所示。

示例 2:

輸入:num = "100", k = 1
輸出:"010"
解釋:輸出可以包含前導 0 ,但輸入保證不會有前導 0 。

示例 3:

輸入:num = "36789", k = 1000
輸出:"36789"
解釋:不需要做任何交換。

示例 4:

輸入:num = "22", k = 22
輸出:"22"

示例 5:

輸入:num = "9438957234785635408", k = 23
輸出:"0345989723478563548"

提示:

  • 1 <= num.length <= 30000
  • num只包含數字且不含有前導 0。
  • 1 <= k <= 10^9

PS:

  這道題有暴力有遞迴,測試用例不到位,真正得方法不需要用就可以過了

class Solution {
public String minInteger(String num, int k) {
if (k == 0)return num;
for (char c = '0' ; c <= '9' ; c++){
int i = num.indexOf(c);
if (i >= 0){
if ( i <= k){
return c + minInteger(num.substring(0,i)+ num.substring(i+1),k - i);
}
}
}
return num;
}
}
class Solution {
void sw(char cs[],int i,int j){
char t = cs[i];
cs[i] =cs[j];
cs[j] = t; } public String minInteger(String num, int k) {
char cs[] = num.toCharArray();
int l = cs.length;
for(int i=0;i<l&&k>0;++i){
int cur = i;
for(int j=i+1;j<l&&j-i<=k;++j){
if(cs[j]<cs[cur]){
cur = j;
}
}
for(int j=cur;j>i&&k>0;--j){
k--;
sw(cs, j, j-1);
} } return new String(cs); }
}

最不堪回收的一次周賽,唉,枉我午飯都沒吃