一、1913. 两个数对之间的最大乘积差
1.题目
1913. 两个数对之间的最大乘积差
两个数对 (a, b) 和 (c, d) 之间的 乘积差 定义为 (a * b) - (c * d) 。 例如,(5, 6) 和 (2, 7) 之间的乘积差是 (5 * 6) - (2 * 7) = 16 。 给你一个整数数组 nums ,选出四个 不同的 下标 w、x、y 和 z ,使数对 (nums[w], nums[x]) 和 (nums[y], nums[z]) 之间的 乘积差 取到 最大值 。 返回以这种方式取得的乘积差中的 最大值 。
2.分析
- 要使得乘积差尽可能大,则
(
a
?
b
)
(a*b)
(a?b) 尽可能大,
(
c
?
d
)
(c*d)
(c?d) 尽可能小。
- 所以对数组排序后,
a
,
b
a,b
a,b 取最大的两个值,
c
,
d
c,d
c,d 取最小的两个值即可。
3.代码
class Solution {
public int maxProductDifference(int[] nums) {
Arrays.sort(nums);
int length = nums.length;
return (nums[length - 1] * nums[length - 2]) - (nums[0] * nums[1]);
}
}
二、976. 三角形的最大周长
1.题目
976. 三角形的最大周长
给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长。 如果不能形成任何面积不为零的三角形,返回 0。
2.分析
- 假设三条边分别为 a , b , c(a > b),要使得这三条边能组成一个三角形,必须满足:
a
+
b
>
c
且
a
?
b
<
c
a+b>c且a-b<c
a+b>c且a?b<c
- 所以求能形成三角形的最大周长,可以先将数组排序,再从最大数开始遍历,只要满足
n
u
m
s
[
i
?
1
]
+
n
u
m
s
[
i
?
2
]
>
n
u
m
s
[
i
]
nums[i - 1] +nums[i - 2] > nums[i]
nums[i?1]+nums[i?2]>nums[i] 的第一个周长就是最大周长(排序后(两边之差小于第三边)必定满足)
3.代码
class Solution {
public int largestPerimeter(int[] nums) {
Arrays.sort(nums);
int i;
for (i = nums.length - 1;i >= 2;i--){
if (nums[i - 1] + nums[i - 2] > nums[i]){
return nums[i - 1] + nums[i - 2] + nums[i];
}
}
return 0;
}
}
三、561. 数组拆分 I
1.题目
561. 数组拆分 I
给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。 返回该 最大总和 。
2.分析
- 举个例子:
- 从例子可以发现,要想数对的较小值的总和尽可能大,就要在
m
i
n
(
a
,
b
)
min(a,b)
min(a,b) 时,尽可能将数组中较大的值保留下来。
- 如果最大值和最小值比较,则保留下来的一定是最小值。
- 如果最大值和第二大的值比较,则可以保留下来第二大的值。
- 所以,只需要将排序后的数组,每两个元素为一对,取较小值的总和,得到的总和就是最大总和。
3.代码
class Solution {
public int arrayPairSum(int[] nums) {
Arrays.sort(nums);
int i,ans = 0;
for (i = 0;i < nums.length;i += 2){
ans += nums[i];
}
return ans;
}
}
四、881. 救生艇
1.题目
881. 救生艇
第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。 返回载到每一个人所需的最小船数。(保证每个人都能被船载)。
2.分析
- 排序后,双指针遍历
对数组
i
n
t
[
]
p
e
o
p
l
e
int[] people
int[]people 进行排序,再进行遍历。 分别用
i
i
i 和
j
j
j 标记数组两边的元素,如果符合
p
e
o
p
l
e
[
j
]
+
p
e
o
p
l
e
[
i
]
<
=
l
i
m
i
t
people[j] + people[i] <= limit
people[j]+people[i]<=limit,说明可以2人一艘船。否则,只能体重较重的人一艘船。 - 注意遍历的边界:
- 如下图的情况,当
i
=
j
i=j
i=j 时,说明最后剩下一个人没上船,所以要将计数
c
o
u
n
t
count
count 加1
3.代码
class Solution {
public int numRescueBoats(int[] people, int limit) {
Arrays.sort(people);
int i = 0,j = people.length - 1,count = 0;
while (i < j){
if (people[j] + people[i] <= limit){
i++;
}
j--;
count++;
}
return i == j ? ++count : count;
}
}
五、324. 摆动排序 II
1.题目
324. 摆动排序 II
给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。 你可以假设所有输入数组都可以得到满足题目要求的结果。
2.分析
- 将原数组克隆出一个新数组,
n
u
m
s
.
c
l
o
n
e
(
)
;
nums.clone();
nums.clone();,并对新数组进行排序。
- 将新数组看成两部分,一部分从下标
j
=
(
l
e
n
g
t
h
?
1
)
>
>
1
j = (length - 1) >> 1
j=(length?1)>>1 位置开始,另一部分从下标
k
=
l
e
n
g
t
h
?
1
k = length - 1
k=length?1 开始。
- 最后,遍历原数组,逆序插入值。当下标为偶数,将新数组下标
j
j
j 对应的值存到原数组中,
j
j
j 自减;当下标为奇数,将新数组下标
k
k
k 对应的值存到原数组中,
k
k
k 自减。
3.代码
class Solution {
public void wiggleSort(int[] nums) {
int i,length = nums.length;
int[] nums_copy = nums.clone();
Arrays.sort(nums_copy);
int j = (length - 1) >> 1,k = length - 1;
for (i = 0;i < length;i++){
if ((i & 1) == 0){
nums[i] = nums_copy[j--];
} else {
nums[i] = nums_copy[k--];
}
}
}
}
六、455. 分发饼干
1.题目
455. 分发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
2.分析
- 将胃口数组
i
n
t
[
]
g
int[] g
int[]g 以及饼干数组
i
n
t
[
]
s
int[] s
int[]s 进行排序
- 优先将饼干满足胃口小的,这样得到满足的数量就是最多的。
3.代码
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int kid = 0,cookie = 0;
while (kid < g.length && cookie < s.length){
if (g[kid] <= s[cookie]){
kid++;
}
cookie++;
}
return kid;
}
}
七、1827. 最少操作使数组递增
1.题目
1827. 最少操作使数组递增
给你一个整数数组 nums (下标从 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 。 比方说,如果 nums = [1,2,3] ,你可以选择增加 nums[1] 得到 nums = [1,3,3] 。 请你返回使 nums 严格递增 的 最少 操作次数。 我们称数组 nums 是 严格递增的 ,当它满足对于所有的 0 <= i < nums.length - 1 都有 nums[i] < nums[i+1] 。一个长度为 1 的数组是严格递增的一种特殊情况。
2.分析
- 因为这里不打算修改数组中的元素,所以定义了一个变量
m
a
x
max
max 来存储上一个元素的值(有可能是存储上一个元素修改过的值)
- 遍历数组,如果当前元素比
m
a
x
max
max 大时,说明还保持着严格递增,直接
c
o
n
t
i
n
u
e
continue
continue 进入下一轮循环。
- 如果当前元素
<
=
m
a
x
<=max
<=max,则计算当前元素自增到等于
m
a
x
+
1
max + 1
max+1,需要自增多少次,累加到变量
c
o
u
n
t
count
count,循环结束后返回。
3.代码
class Solution {
public int minOperations(int[] nums) {
int i,count = 0;
int max = nums[0];
for (i = 1;i < nums.length;i++){
if (nums[i] > max){
max = nums[i];
continue;
}
max++;
count += max - nums[i];
}
return count;
}
}
八、945. 使数组唯一的最小增量
1.题目
945. 使数组唯一的最小增量
给你一个整数数组 nums 。每次 move 操作将会选择任意一个满足 0 <= i < nums.length 的下标 i,并将 nums[i] 递增 1。 返回使 nums 中的每个值都变成唯一的所需要的最少操作次数。
2.分析
- 数组唯一的最小增量,其实可以解读为:数组排序后,最少操作使数组递增。
- 所以只要将数组排序后,再以上一题同样的方法来计算操作次数即可。
3.代码
class Solution {
public int minIncrementForUnique(int[] nums) {
Arrays.sort(nums);
int i,count = 0;
int max = nums[0];
for (i = 1;i < nums.length;i++){
if (nums[i] > max){
max = nums[i];
continue;
}
count += ++max - nums[i];
}
return count;
}
}
九、611. 有效三角形的个数
1.题目
611. 有效三角形的个数
给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。
2.分析
- 对数组进行排序。
- 确定一条最长边
i
i
i,再令另外两条边分别从
l
=
0
,
r
=
i
?
1
l = 0,r = i - 1
l=0,r=i?1 开始遍历。
- 如果判断出现了
n
u
m
s
[
l
]
+
n
u
m
s
[
r
]
>
n
u
m
s
[
i
]
nums[l] + nums[r] > nums[i]
nums[l]+nums[r]>nums[i],那么
l
l
l 和
r
r
r
之间的元素也必定满足这个条件,不用再遍历这些元素,可以直接累加:
c
o
u
n
t
+
=
r
?
l
;
count += r - l;
count+=r?l;,累加后
r
r
r 左移一位。否则,
l
l
l 右移一位。
3.代码
class Solution {
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
int i,count = 0;
for (i = nums.length - 1;i >= 2;i--){
int l = 0,r = i - 1;
while (l < r){
if (nums[l] + nums[r] > nums[i]){
count += r - l;
r--;
} else {
l++;
}
}
}
return count;
}
}
|