@@ -23,126 +23,67 @@ https://leetcode-cn.com/problems/best-sightseeing-pair/description/
2323
2424## 思路
2525
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+ ```
6138
62- - 数组最左边的元素
63- - 数组最右边的元素
64- - 数组中间的元素(我采用的是这种,大家可以尝试下别的)
65- - 数组随机一项元素
39+ 我们思考如何优化。 其实我们可以遍历一遍数组,对于数组的每一项` A[j] - j ` 我们都去前面找` 最大 ` 的 A[ i] + i (这样才能保证结果最大)。
6640
67- ![ sort-an-array-2 ] ( ../assets/problems/912.sort-an-array-2.png )
41+ 我们考虑使用动态规划来解决, 我们使用 dp [ i ] 来表示 数组 A 前 i 项的 ` A[i] + i ` 的最大值。
6842
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+ ```
7054
71- > 图片中的轴元素是最后面的元素,而提供的解法是中间元素,这点需要注意,但是这并不影响理解 。
55+ 如上其实我们发现,dp [ i + 1 ] 只和 dp [ i ] 有关,这是一个空间优化的信号。我们其实可以使用一个变量来记录,而不必要使用一个数组,代码见下方 。
7256
7357## 关键点解析
7458
75- - 排序算法
76- - 注意题目的限制条件从而选择合适的算法
77-
7859## 代码
7960
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
10071```
10172
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
14089```
141-
142- ## 扩展
143-
144- - 你是否可以用其他方式排序算法解决
145-
146- ## 参考
147-
148- - [ QuickSort - geeksforgeeks] ( https://www.geeksforgeeks.org/quick-sort/ )
0 commit comments