@@ -23,126 +23,67 @@ https://leetcode-cn.com/problems/best-sightseeing-pair/description/
23
23
24
24
## 思路
25
25
26
- 这是一个很少见的直接考察` 排序 ` 的题目。 其他题目一般都是暗含` 排序 ` ,这道题则简单粗暴,直接让你排序。
27
- 并且这道题目的难度是` Medium ` , 笔者感觉有点不可思议。
28
-
29
- 我们先来看题目的限制条件,这其实在选择算法的过程中是重要的。 看到这道题的时候,大脑就闪现出了各种排序算法,
30
- 这也算是一个复习` 排序算法 ` 的机会吧。
31
-
32
- 题目的限制条件是有两个,第一是元素个数不超过 10k,这个不算大。 另外一个是数组中的每一项范围都是` -50k ` 到` 50k ` (包含左右区间)。
33
- 看到这里,基本我就排除了时间复杂度为 O(n^2)的算法。
34
-
35
- > 我没有试时间复杂度 O(n^2) 的解法,大家可以试一下,看是不是会 TLE。
36
-
37
- 剩下的就是基于比较的` nlogn ` 算法,以及基于特定条件的 O(n)算法。
38
-
39
- 由于平时很少用到` 计数排序 ` 等 O(n)的排序算法,一方面是空间复杂度不是常量,另一方面是其要求数据范围不是很大才行,不然会浪费很多空间。
40
- 但是这道题我感觉可以试一下。 在这里,我用了两种方法,一种是` 计数排序 ` ,一种是` 快速排序 ` 来解决。 大家也可以尝试用别的解法来解决。
41
-
42
- ### 解法一 - 计数排序
43
-
44
- 时间复杂度 O(n)空间复杂度 O(m) m 为数组中值的取值范围,在这道题就是` 50000 * 2 + 1 ` 。
45
-
46
- 我们只需要准备一个数组取值范围的数字,然后遍历一遍,将每一个元素放到这个数组对应位置就好了,
47
- 放的规则是` 索引为数字的值,value为出现的次数 ` 。
48
-
49
- 这样一次遍历,我们统计出了所有的数字出现的位置和次数。 我们再来一次遍历,将其输出到即可。
50
-
51
- ![ sort-an-array-1] ( ../assets/problems/912.sort-an-array-1.png )
52
-
53
- ### 解法二 - 快速排序
54
-
55
- 快速排序和归并排序都是分支思想来进行排序的算法, 并且二者都非常流行。 快速排序的核心点在于选择轴元素。
56
-
57
- 每次我们将数组分成两部分,一部分是比 pivot(轴元素)大的,另一部分是不比 pivot 大的。 我们不断重复这个过程,
58
- 直到问题的规模缩小的寻常(即只有一个元素的情况)。
59
-
60
- 快排的核心点在于如何选择轴元素,一般而言,选择轴元素有三种策略:
26
+ 最简单的思路就是两两组合,找出最大的,妥妥超时,我们来看下代码:
27
+
28
+ ``` python
29
+ class Solution :
30
+ def maxScoreSightseeingPair (self , A : List[int ]) -> int :
31
+ n = len (A)
32
+ res = 0
33
+ for i in range (n - 1 ):
34
+ for j in range (i + 1 , n):
35
+ res = max (res, A[i] + A[j] + i - j)
36
+ return res
37
+ ```
61
38
62
- - 数组最左边的元素
63
- - 数组最右边的元素
64
- - 数组中间的元素(我采用的是这种,大家可以尝试下别的)
65
- - 数组随机一项元素
39
+ 我们思考如何优化。 其实我们可以遍历一遍数组,对于数组的每一项` A[j] - j ` 我们都去前面找` 最大 ` 的 A[ i] + i (这样才能保证结果最大)。
66
40
67
- ![ sort-an-array-2 ] ( ../assets/problems/912.sort-an-array-2.png )
41
+ 我们考虑使用动态规划来解决, 我们使用 dp [ i ] 来表示 数组 A 前 i 项的 ` A[i] + i ` 的最大值。
68
42
69
- (图片来自: https://www.geeksforgeeks.org/quick-sort/ )
43
+ ``` python
44
+ class Solution :
45
+ def maxScoreSightseeingPair (self , A : List[int ]) -> int :
46
+ n = len (A)
47
+ dp = [float (' -inf' )] * (n + 1 )
48
+ res = 0
49
+ for i in range (n):
50
+ dp[i + 1 ] = max (dp[i], A[i] + i)
51
+ res = max (res, dp[i] + A[i] - i)
52
+ return res
53
+ ```
70
54
71
- > 图片中的轴元素是最后面的元素,而提供的解法是中间元素,这点需要注意,但是这并不影响理解 。
55
+ 如上其实我们发现,dp [ i + 1 ] 只和 dp [ i ] 有关,这是一个空间优化的信号。我们其实可以使用一个变量来记录,而不必要使用一个数组,代码见下方 。
72
56
73
57
## 关键点解析
74
58
75
- - 排序算法
76
- - 注意题目的限制条件从而选择合适的算法
77
-
78
59
## 代码
79
60
80
- 计数排序:
81
-
82
- 代码支持: JavaScript
83
-
84
- ``` js
85
- /**
86
- * @param {number[]} nums
87
- * @return {number[]}
88
- */
89
- var sortArray = function (nums ) {
90
- const counts = Array (50000 * 2 + 1 ).fill (0 );
91
- const res = [];
92
- for (const num of nums) counts[50000 + num] += 1 ;
93
- for (let i in counts) {
94
- while (counts[i]-- ) {
95
- res .push (i - 50000 );
96
- }
97
- }
98
- return res;
99
- };
61
+ ``` python
62
+ class Solution :
63
+ def maxScoreSightseeingPair (self , A : List[int ]) -> int :
64
+ n = len (A)
65
+ pre = A[0 ] + 0
66
+ res = 0
67
+ for i in range (1 , n):
68
+ res = max (res, pre + A[i] - i)
69
+ pre = max (pre, A[i] + i)
70
+ return res
100
71
```
101
72
102
- 快速排序:
103
-
104
- 代码支持: JavaScript
105
-
106
- ``` js
107
- function swap (nums , a , b ) {
108
- const temp = nums[a];
109
- nums[a] = nums[b];
110
- nums[b] = temp;
111
- }
112
-
113
- function helper (nums , start , end ) {
114
- if (start >= end) return ;
115
- const pivotIndex = start + ((end - start) >>> 1 );
116
- const pivot = nums[pivotIndex];
117
- let i = start;
118
- let j = end;
119
- while (i <= j) {
120
- while (nums[i] < pivot) i++ ;
121
- while (nums[j] > pivot) j-- ;
122
- if (i <= j) {
123
- swap (nums, i, j);
124
- i++ ;
125
- j-- ;
126
- }
127
- }
128
- helper (nums, start, j);
129
- helper (nums, i, end);
130
- }
131
-
132
- /**
133
- * @param {number[]} nums
134
- * @return {number[]}
135
- */
136
- var sortArray = function (nums ) {
137
- helper (nums, 0 , nums .length - 1 );
138
- return nums;
139
- };
73
+ ## 小技巧
74
+
75
+ Python 的代码如果不使用 max,而是使用 if else 效率目测会更高,大家可以试一下。
76
+
77
+ ``` python
78
+ class Solution :
79
+ def maxScoreSightseeingPair (self , A : List[int ]) -> int :
80
+ n = len (A)
81
+ pre = A[0 ] + 0
82
+ res = 0
83
+ for i in range (1 , n):
84
+ # res = max(res, pre + A[i] - i)
85
+ # pre = max(pre, A[i] + i)
86
+ res = res if res > pre + A[i] - i else pre + A[i] - i
87
+ pre = pre if pre > A[i] + i else A[i] + i
88
+ return res
140
89
```
141
-
142
- ## 扩展
143
-
144
- - 你是否可以用其他方式排序算法解决
145
-
146
- ## 参考
147
-
148
- - [ QuickSort - geeksforgeeks] ( https://www.geeksforgeeks.org/quick-sort/ )
0 commit comments