@@ -242,9 +242,9 @@ func main() {
242
242
243
243
1、 数据状况层面是否可以优化
244
244
245
- 2、 问题本身是否可以优化。单调性,首位指针 (头指针往右走,尾指针往左走)等
245
+ 2、 问题本身是否可以优化。单调性,首尾指针 (头指针往右走,尾指针往左走)等
246
246
247
- > 遇到一个问题我们先观察,问题本身和范围是否可以建立单调性,至于需要用哪个原型来解决,串口和首位指针法是常见的流程 。所以窗口和首位指针主要用来解决单调性的
247
+ > 遇到一个问题我们先观察,问题本身和范围是否可以建立单调性,至于需要用哪个原型来解决,窗口和首位指针法是常见的流程 。所以窗口和首位指针主要用来解决单调性的
248
248
249
249
## 1.2 单调栈
250
250
@@ -278,182 +278,141 @@ func main() {
278
278
> 如果存在相等元素的情况,我们栈中每个元素保存为list表示相等元素列表。无法直接进入单调栈时,弹出list最右侧的元素,该元素右侧最近的比自己小的数,就是迫使它弹出的那个数。该元素左侧最近比它小的数,就是自身的这个list压着的的list的最右的数。list的相同元素有两种情况,一种是两个数相等且挨着,另外一种是某个位置释放了中间位置的数后遇到相等元素,进入一个list中去。画栈模拟可看出
279
279
280
280
281
- ``` Java
282
-
283
- package class01 ;
281
+ ``` Go
282
+ package main
284
283
285
- import java.util.List ;
286
- import java.util.ArrayList ;
287
- import java.util.Stack ;
284
+ import " fmt"
288
285
289
- public class Code03_MonotonousStack {
286
+ // 单调栈
290
287
291
- // 数组中没有重复值的情况
292
- public static int [][] getNearLessNoRepeat (int [] arr ) {
293
- int [][] res = new int [arr. length][2 ];
294
- Stack<Integer > stack = new Stack<> ();
295
- for (int i = 0 ; i < arr. length; i++ ) {
296
- while (! stack. isEmpty() && arr[stack. peek()] > arr[i]) {
297
- int popIndex = stack. pop();
298
- int leftLessIndex = stack. isEmpty() ? - 1 : stack. peek();
299
- res[popIndex][0 ] = leftLessIndex;
300
- res[popIndex][1 ] = i;
301
- }
302
- stack. push(i);
303
- }
304
- while (! stack. isEmpty()) {
305
- int popIndex = stack. pop();
306
- int leftLessIndex = stack. isEmpty() ? - 1 : stack. peek();
307
- res[popIndex][0 ] = leftLessIndex;
308
- res[popIndex][1 ] = - 1 ;
309
- }
310
- return res;
288
+ // 数组中没有重复值的情况
289
+ func getNearLessNoRepeat (arr []int ) [][]int {
290
+ res := make ([][]int , len (arr))
291
+ for i := 0 ; i < len (arr); i++ {
292
+ res[i] = make ([]int , 2 )
311
293
}
312
294
313
- // arr [3, 2, 1, 4, 5]
314
- // 0 1 2 3 4
315
-
316
- // 表示 0这个数左边最近比0小的没有,位置是-1,右边1。1位置数左边最近比0小的没有-1,右边2
317
- // [
318
- // 0 : [-1, 1 ]
319
- // 1 : [-1, 2 ]
320
-
321
- // ]
322
- // 数组中存在重复值的情况
323
- public static int [][] getNearLess (int [] arr ) {
324
- int [][] res = new int [arr. length][2 ];
325
-
326
-
327
- // List<Integer> -> 放的是位置,同样值的东西,位置压在一起
328
- // 代表值 底 -> 顶 小 -> 大
329
- Stack<List<Integer > > stack = new Stack<> ();
330
- for (int i = 0 ; i < arr. length; i++ ) { // i -> arr[i] 进栈
331
- // 栈底 -> 栈顶, 小 -> 大
332
- while (! stack. isEmpty() && arr[stack. peek(). get(0 )] > arr[i]) {
333
- List<Integer > popIs = stack. pop();
334
- // 取位于下面位置的列表中,最晚加入的那个
335
- int leftLessIndex = stack. isEmpty() ? - 1 : stack. peek(). get(stack. peek(). size() - 1 );
336
- for (Integer popi : popIs) {
337
- res[popi][0 ] = leftLessIndex;
338
- res[popi][1 ] = i;
339
- }
340
- }
341
- // 相等的、比你小的
342
- if (! stack. isEmpty() && arr[stack. peek(). get(0 )] == arr[i]) {
343
- stack. peek(). add(Integer . valueOf(i));
295
+ // 模拟一个栈
296
+ stack := make ([]int , 0 )
297
+ for i := 0 ; i < len (arr); i++ {
298
+ for len (stack) != 0 && arr[stack[len (stack) - 1 ]] > arr[i] {
299
+ // 出栈 stack pop
300
+ popIndex := stack[len (stack) - 1 ]
301
+ stack = stack[:len (stack) - 1 ]
302
+
303
+ leftLessIndex := 0
304
+ if len (stack) == 0 {
305
+ leftLessIndex = -1
344
306
} else {
345
- ArrayList<Integer > list = new ArrayList<> ();
346
- list. add(i);
347
- stack. push(list);
348
- }
349
- }
350
- while (! stack. isEmpty()) {
351
- List<Integer > popIs = stack. pop();
352
- // 取位于下面位置的列表中,最晚加入的那个
353
- int leftLessIndex = stack. isEmpty() ? - 1 : stack. peek(). get(stack. peek(). size() - 1 );
354
- for (Integer popi : popIs) {
355
- res[popi][0 ] = leftLessIndex;
356
- res[popi][1 ] = - 1 ;
307
+ leftLessIndex = stack[len (stack) - 1 ]
357
308
}
309
+
310
+ res[popIndex][0 ] = leftLessIndex
311
+ res[popIndex][1 ] = i
358
312
}
359
- return res;
313
+ // stack push i
314
+ stack = append (stack, i)
360
315
}
361
316
362
- // for test
363
- public static int [] getRandomArrayNoRepeat ( int size ) {
364
- int [] arr = new int [( int ) ( Math . random() * size) + 1 ];
365
- for ( int i = 0 ; i < arr . length; i ++ ) {
366
- arr[i] = i;
367
- }
368
- for ( int i = 0 ; i < arr . length; i ++ ) {
369
- int swapIndex = ( int ) ( Math . random() * arr . length);
370
- int tmp = arr[swapIndex];
371
- arr[swapIndex] = arr[i];
372
- arr[i] = tmp;
317
+ for len (stack) != 0 {
318
+ // 出栈 stack pop
319
+ popIndex := stack[ len (stack) - 1 ]
320
+ stack = stack[: len (stack) - 1 ]
321
+
322
+ leftLessIndex := 0
323
+ if len (stack) == 0 {
324
+ leftLessIndex = - 1
325
+ } else {
326
+ // leftLessIndex = stack peek
327
+ leftLessIndex = stack[ len (stack) - 1 ]
373
328
}
374
- return arr;
329
+
330
+ res[popIndex][0 ] = leftLessIndex
331
+ res[popIndex][1 ] = -1
375
332
}
376
333
377
- // for test
378
- public static int [] getRandomArray (int size , int max ) {
379
- int [] arr = new int [(int ) (Math . random() * size) + 1 ];
380
- for (int i = 0 ; i < arr. length; i++ ) {
381
- arr[i] = (int ) (Math . random() * max) - (int ) (Math . random() * max);
382
- }
383
- return arr;
334
+ return res
335
+ }
336
+
337
+ // arr [3, 2, 1, 4, 5]
338
+ // 0 1 2 3 4
339
+
340
+ // 表示 0这个数左边最近比0小的没有,位置是-1,右边1。1位置数左边最近比0小的没有-1,右边2
341
+ // [
342
+ // 0 : [-1, 1 ]
343
+ // 1 : [-1, 2 ]
344
+
345
+ // ]
346
+ // 数组中存在重复值的情况
347
+ func getNearLess (arr []int ) [][]int {
348
+ res := make ([][]int , len (arr))
349
+ for i := 0 ; i < len (arr); i++ {
350
+ res[i] = make ([]int , 2 )
384
351
}
385
352
386
- // for test
387
- public static int [][] rightWay (int [] arr ) {
388
- int [][] res = new int [arr. length][2 ];
389
- for (int i = 0 ; i < arr. length; i++ ) {
390
- int leftLessIndex = - 1 ;
391
- int rightLessIndex = - 1 ;
392
- int cur = i - 1 ;
393
- while (cur >= 0 ) {
394
- if (arr[cur] < arr[i]) {
395
- leftLessIndex = cur;
396
- break ;
397
- }
398
- cur-- ;
399
- }
400
- cur = i + 1 ;
401
- while (cur < arr. length) {
402
- if (arr[cur] < arr[i]) {
403
- rightLessIndex = cur;
404
- break ;
405
- }
406
- cur++ ;
353
+ // []int -> 放的是位置,同样值的东西,位置压在一起
354
+ // 代表值 底 -> 顶 小 -> 大
355
+ stack := make ([][]int , 0 )
356
+
357
+ for i := 0 ; i < len (arr); i++ { // i -> arr[i] 进栈
358
+ // 栈底 -> 栈顶, 小 -> 大
359
+ for len (stack) != 0 && arr[stack[len (stack) - 1 ][0 ]] > arr[i] {
360
+ // 出栈 stack pop
361
+ popIs := stack[len (stack) - 1 ]
362
+ stack = stack[:len (stack) - 1 ]
363
+
364
+ // 取位于下面位置的列表中,最晚加入的那个
365
+ leftLessIndex := 0
366
+ if len (stack) == 0 {
367
+ leftLessIndex = -1
368
+ } else {
369
+ leftLessIndex = stack[len (stack) - 1 ][len (stack[len (stack) - 1 ]) - 1 ]
407
370
}
408
- res[i][0 ] = leftLessIndex;
409
- res[i][1 ] = rightLessIndex;
410
- }
411
- return res;
412
- }
413
371
414
- // for test
415
- public static boolean isEqual (int [][] res1 , int [][] res2 ) {
416
- if (res1. length != res2. length) {
417
- return false ;
418
- }
419
- for (int i = 0 ; i < res1. length; i++ ) {
420
- if (res1[i][0 ] != res2[i][0 ] || res1[i][1 ] != res2[i][1 ]) {
421
- return false ;
372
+ for _,popi := range popIs {
373
+ res[popi][0 ] = leftLessIndex
374
+ res[popi][1 ] = i
422
375
}
423
376
}
424
377
425
- return true ;
378
+ // 相等的、比你小的
379
+ if len (stack) != 0 && arr[stack[len (stack) - 1 ][0 ]] == arr[i] {
380
+ stack[len (stack) - 1 ] = append (stack[len (stack) - 1 ], i)
381
+ } else {
382
+ list := make ([]int , 0 )
383
+ list = append (list, i)
384
+ // stack push
385
+ stack = append (stack, list)
386
+ }
426
387
}
427
388
428
- // for test
429
- public static void printArray (int [] arr ) {
430
- for (int i = 0 ; i < arr. length; i++ ) {
431
- System . out. print(arr[i] + " " );
389
+ for len (stack) != 0 {
390
+ // stack pop
391
+ popIs := stack[len (stack) - 1 ]
392
+ stack = stack[:len (stack) - 1 ]
393
+
394
+ // 取位于下面位置的列表中,最晚加入的那个
395
+ leftLessIndex := 0
396
+ if len (stack) == 0 {
397
+ leftLessIndex = -1
398
+ } else {
399
+ leftLessIndex = stack[len (stack) - 1 ][len (stack[len (stack) - 1 ]) - 1 ]
432
400
}
433
- System . out. println();
434
- }
435
401
436
- public static void main (String [] args ) {
437
- int size = 10 ;
438
- int max = 20 ;
439
- int testTimes = 2000000 ;
440
- for (int i = 0 ; i < testTimes; i++ ) {
441
- int [] arr1 = getRandomArrayNoRepeat(size);
442
- int [] arr2 = getRandomArray(size, max);
443
- if (! isEqual(getNearLessNoRepeat(arr1), rightWay(arr1))) {
444
- System . out. println(" Oops!" );
445
- printArray(arr1);
446
- break ;
447
- }
448
- if (! isEqual(getNearLess(arr2), rightWay(arr2))) {
449
- System . out. println(" Oops!" );
450
- printArray(arr2);
451
- break ;
452
- }
402
+ for _,popi := range popIs {
403
+ res[popi][0 ] = leftLessIndex
404
+ res[popi][1 ] = -1
453
405
}
454
406
}
407
+ return res
455
408
}
456
409
410
+ func main () {
411
+ arr := []int {4 , 3 , 5 , 6 , 7 }
412
+ fmt.Println (getNearLessNoRepeat (arr))
413
+ arr = []int {4 , 3 , 5 , 4 , 3 , 3 , 6 , 7 }
414
+ fmt.Println (getNearLess (arr))
415
+ }
457
416
```
458
417
459
418
### 1.2.2 单调栈的应用
0 commit comments