@@ -325,195 +325,113 @@ T(N) = T((1/3)N) + T((2/3)N) + O(N)
325
325
326
326
> 空间复杂度:O(logN)。空间复杂度产生于每次递归partion之后,我们需要申请额外的空间变量保存相等区域的左右两侧的位置。那么每次partion需要申请两个变量,多少次partion?实质是该递归树被分了多少层,树的高度,有好有坏,最好logN,最差N。随机选择num之后,期望仍然是概率累加,收敛于O(logN)。
327
327
328
- ``` Java
329
- package class03 ;
330
-
331
- public class Code03_PartitionAndQuickSort {
332
-
333
- public static void swap (int [] arr , int i , int j ) {
334
- int tmp = arr[i];
335
- arr[i] = arr[j];
336
- arr[j] = tmp;
337
- }
338
-
339
- // partion问题
340
- public static int partition (int [] arr , int L , int R ) {
341
- if (L > R ) {
342
- return - 1 ;
343
- }
344
- if (L == R ) {
345
- return L ;
346
- }
347
- int lessEqual = L - 1 ;
348
- int index = L ;
349
- while (index < R ) {
350
- if (arr[index] <= arr[R ]) {
351
- swap(arr, index, ++ lessEqual);
352
- }
353
- index++ ;
354
- }
355
- swap(arr, ++ lessEqual, R );
356
- return lessEqual;
357
- }
358
-
359
- // arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值
360
- // 小于arr[R]放左侧 等于arr[R]放中间 大于arr[R]放右边
361
- // 返回中间区域的左右边界
362
- public static int [] netherlandsFlag (int [] arr , int L , int R ) {
363
- // 不存在荷兰国旗问题
364
- if (L > R ) {
365
- return new int [] { - 1 , - 1 };
366
- }
367
- // 已经都是等于区域,由于用R做划分返回R位置
368
- if (L == R ) {
369
- return new int [] { L , R };
370
- }
371
- int less = L - 1 ; // < 区 右边界
372
- int more = R ; // > 区 左边界
373
- int index = L ;
374
- while (index < more) {
375
- // 当前值等于右边界,不做处理,index++
376
- if (arr[index] == arr[R ]) {
377
- index++ ;
378
- // 小于交换当前值和左边界的值
379
- } else if (arr[index] < arr[R ]) {
380
- swap(arr, index++ , ++ less);
381
- // 大于右边界的值
382
- } else {
383
- swap(arr, index, -- more);
384
- }
385
- }
386
- // 比较完之后,把R位置的数,调整到等于区域的右边,至此大于区域才是真正意义上的大于区域
387
- swap(arr, more, R );
388
- return new int [] { less + 1 , more };
389
- }
390
-
391
- public static void quickSort1 (int [] arr ) {
392
- if (arr == null || arr. length < 2 ) {
393
- return ;
394
- }
395
- process1(arr, 0 , arr. length - 1 );
396
- }
397
-
398
- public static void process1 (int [] arr , int L , int R ) {
399
- if (L >= R ) {
400
- return ;
401
- }
402
- // L..R上partition 标记位为arr[R] 数组被分成 [ <=arr[R] arr[R] >arr[R] ],M为partion之后标记位处在的位置
403
- int M = partition(arr, L , R );
404
- process1(arr, L , M - 1 );
405
- process1(arr, M + 1 , R );
406
- }
328
+ ``` Go
329
+ package main
407
330
408
- public static void quickSort2 ( int [] arr ) {
409
- if (arr == null || arr . length < 2 ) {
410
- return ;
411
- }
412
- process2( arr, 0 , arr . length - 1 );
413
- }
331
+ // swap 交换数组中的两个位置的数
332
+ func swap (arr [] int , i , j int ) {
333
+ tmp := arr[i]
334
+ arr[i] = arr[j]
335
+ arr[j] = tmp
336
+ }
414
337
415
- public static void process2 (int [] arr , int L , int R ) {
416
- if (L >= R ) {
417
- return ;
338
+ // partition 对数组进行partition处理
339
+ func partition (arr []int , L , R int ) int {
340
+ if L > R {
341
+ return -1
342
+ }
343
+ if L == R {
344
+ return L
345
+ }
346
+ // 选定左边界的左边一个位置作为小于区域的起点
347
+ lessEqual := L - 1
348
+ index := L
349
+ // 每次搞定一个位置
350
+ for index < R {
351
+ if arr[index] <= arr[R] {
352
+ lessEqual++
353
+ swap (arr, index, lessEqual)
418
354
}
419
- // 每次partion返回等于区域的范围
420
- int [] equalArea = netherlandsFlag(arr, L , R );
421
- // 对等于区域左边的小于区域递归,partion
422
- process2(arr, L , equalArea[0 ] - 1 );
423
- // 对等于区域右边的大于区域递归,partion
424
- process2(arr, equalArea[1 ] + 1 , R );
355
+ index++
425
356
}
357
+ lessEqual++
358
+ swap (arr, lessEqual, R)
359
+ return lessEqual
360
+ }
426
361
427
- public static void quickSort3 (int [] arr ) {
428
- if (arr == null || arr. length < 2 ) {
429
- return ;
362
+ // arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值
363
+ // 小于arr[R]放左侧 等于arr[R]放中间 大于arr[R]放右边
364
+ // 返回中间区域的左右边界
365
+ func netherlandsFlag (arr []int , L , R int ) []int {
366
+ // 不存在荷兰国旗问题
367
+ if L > R {
368
+ return []int {-1 , -1 }
369
+ }
370
+
371
+ // 已经都是等于区域,由于用R做划分返回R位置
372
+ if L == R {
373
+ return []int {L, R}
374
+ }
375
+
376
+ // < 区 右边界
377
+ less := L - 1
378
+ // > 区 左边界
379
+ more := R
380
+ index := L
381
+ for index < more {
382
+ // 当前值等于右边界,不做处理,index++
383
+ if arr[index] == arr[R] {
384
+ index++
385
+ } else if arr[index] < arr[R] { // 小于交换当前值和左边界的值
386
+ less++
387
+ swap (arr, index, less)
388
+ index++
389
+ } else { // 大于右边界的值
390
+ more--
391
+ swap (arr, index, more)
430
392
}
431
- process3(arr, 0 , arr. length - 1 );
432
393
}
394
+ // 比较完之后,把R位置的数,调整到等于区域的右边,至此大于区域才是真正意义上的大于区域
395
+ swap (arr, more, R)
396
+ return []int {less + 1 , more}
397
+ }
433
398
434
- public static void process3 (int [] arr , int L , int R ) {
435
- if (L >= R ) {
436
- return ;
437
- }
438
- // 随机选择位置,与arr[R]上的数做交换
439
- swap(arr, L + (int ) (Math . random() * (R - L + 1 )), R );
440
- int [] equalArea = netherlandsFlag(arr, L , R );
441
- process3(arr, L , equalArea[0 ] - 1 );
442
- process3(arr, equalArea[1 ] + 1 , R );
399
+ func QuickSort1 (arr []int ) {
400
+ if len (arr) < 2 {
401
+ return
443
402
}
444
403
445
- // for test
446
- public static int [] generateRandomArray (int maxSize , int maxValue ) {
447
- int [] arr = new int [(int ) ((maxSize + 1 ) * Math . random())];
448
- for (int i = 0 ; i < arr. length; i++ ) {
449
- arr[i] = (int ) ((maxValue + 1 ) * Math . random()) - (int ) (maxValue * Math . random());
450
- }
451
- return arr;
452
- }
404
+ sortByPartition (arr, 0 , len (arr)-1 )
405
+ }
453
406
454
- // for test
455
- public static int [] copyArray (int [] arr ) {
456
- if (arr == null ) {
457
- return null ;
458
- }
459
- int [] res = new int [arr. length];
460
- for (int i = 0 ; i < arr. length; i++ ) {
461
- res[i] = arr[i];
462
- }
463
- return res;
407
+ func sortByPartition (arr []int , L int , R int ) {
408
+ if L >= R {
409
+ return
464
410
}
465
411
466
- // for test
467
- public static boolean isEqual (int [] arr1 , int [] arr2 ) {
468
- if ((arr1 == null && arr2 != null ) || (arr1 != null && arr2 == null )) {
469
- return false ;
470
- }
471
- if (arr1 == null && arr2 == null ) {
472
- return true ;
473
- }
474
- if (arr1. length != arr2. length) {
475
- return false ;
476
- }
477
- for (int i = 0 ; i < arr1. length; i++ ) {
478
- if (arr1[i] != arr2[i]) {
479
- return false ;
480
- }
481
- }
482
- return true ;
483
- }
412
+ // L到R上进行partition 标记位为arr[R] 数组被分成 [ <=arr[R] arr[R] >arr[R] ],M为partition之后标记位处在的位置
413
+ M := partition (arr, L, R)
414
+ sortByPartition (arr, L, M-1 )
415
+ sortByPartition (arr, M+1 , R)
416
+ }
484
417
485
- // for test
486
- public static void printArray (int [] arr ) {
487
- if (arr == null ) {
488
- return ;
489
- }
490
- for (int i = 0 ; i < arr. length; i++ ) {
491
- System . out. print(arr[i] + " " );
492
- }
493
- System . out. println();
418
+ func QuickSort2 (arr []int ) {
419
+ if len (arr) < 2 {
420
+ return
494
421
}
422
+ sortByNetherlandsFlag (arr, 0 , len (arr)-1 )
423
+ }
495
424
496
- // for test
497
- public static void main (String [] args ) {
498
- int testTime = 500000 ;
499
- int maxSize = 100 ;
500
- int maxValue = 100 ;
501
- boolean succeed = true ;
502
- for (int i = 0 ; i < testTime; i++ ) {
503
- int [] arr1 = generateRandomArray(maxSize, maxValue);
504
- int [] arr2 = copyArray(arr1);
505
- int [] arr3 = copyArray(arr1);
506
- quickSort1(arr1);
507
- quickSort2(arr2);
508
- quickSort3(arr3);
509
- if (! isEqual(arr1, arr2) || ! isEqual(arr2, arr3)) {
510
- succeed = false ;
511
- break ;
512
- }
513
- }
514
- System . out. println(succeed ? " Nice!" : " Oops!" );
515
-
425
+ func sortByNetherlandsFlag (arr []int , L int , R int ) {
426
+ if L >= R {
427
+ return
516
428
}
517
429
430
+ // 每次partition返回等于区域的范围,荷兰国旗问题
431
+ equalArea := netherlandsFlag (arr, L, R)
432
+ // 对等于区域左边的小于区域递归,partition
433
+ sortByNetherlandsFlag (arr, L, equalArea[0 ]-1 )
434
+ // 对等于区域右边的大于区域递归,partition
435
+ sortByNetherlandsFlag (arr, equalArea[1 ]+1 , R)
518
436
}
519
437
```
0 commit comments