768. 最多能完成排序的块 II
难度:困难
arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。
我们最多能将数组分成多少块?
示例 1:
输入: arr = [5,4,3,2,1]
输出: 1
解释:
将数组分成2块或者更多块,都无法得到所需的结果。
例如,分成 [5, 4], [3, 2, 1] 的结果是 [4, 5, 1, 2, 3],这不是有序的数组。
示例 2:
输入: arr = [2,1,3,4,4]
输出: 4
解释:
我们可以把它分成两块,例如 [2, 1], [3, 4, 4]。
然而,分成 [2, 1], [3], [4], [4] 可以得到最多的块数。
注意:
arr的长度在[1, 2000]之间。
arr[i]的大小在[0, 10**8]之间。
解:
执行用时 : 7 ms, 在Max Chunks To Make Sorted II的Java提交中击败了65.63% 的用户
内存消耗 : 40.2 MB, 在Max Chunks To Make Sorted II的Java提交中击败了100.00% 的用户
思路:将数组排序,对排序后的数组与原数组分别做累加操作,某时刻两者的和相同时,证明此处可以分块。
Code:
class Solution {
public int maxChunksToSorted(int[] arr) {
int sorted[]=arr.clone();
Arrays.sort(sorted);
long sumA=0;
long sumB=0;
int block=0;
for(int i=0;i<arr.length;++i){
sumA+=arr[i];
sumB+=sorted[i];
if(sumA==sumB)
block++;
}
return block;
}
}
78. 子集
难度:中等
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
解:
执行用时 : 2 ms, 在Subsets的Java提交中击败了93.04% 的用户
内存消耗 : 36.1 MB, 在Subsets的Java提交中击败了64.64% 的用户
思路:回溯
class Solution {
public List<List<Integer>> list=new ArrayList<>();
public List<Integer> llist=new ArrayList<>();
public void solu(int[] nums,int i){
list.add(new ArrayList<>(llist));
for(int j=i;j<nums.length;++j){
llist.add(nums[j]);
solu(nums,j+1);
llist.remove(llist.size()-1);
}
}
public List<List<Integer>> subsets(int[] nums) {
solu(nums,0);
return list;
}
}
120. 三角形最小路径和
难度:中等
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
解:
执行用时 : 5 ms, 在Triangle的Java提交中击败了78.56% 的用户
内存消耗 : 36.9 MB, 在Triangle的Java提交中击败了82.87% 的用户
思路:dp
Code:
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if(triangle.size()==1) //只有一层,直接返回
return triangle.get(0).get(0);
int dp[][]=new int[triangle.size()][triangle.size()]; //dp[i][j]表示到达第i层第j个的最短路径
//直接计算前两层
dp[0][0]=triangle.get(0).get(0);
dp[1][0]=dp[0][0]+triangle.get(1).get(0);
dp[1][1]=dp[0][0]+triangle.get(1).get(1);
for(int i=2;i<triangle.size();++i){
for(int j=0;j<=i;++j){
//每层的边缘都只能从上一层的一个点到达
if(j==0)
dp[i][j]=dp[i-1][j]+triangle.get(i).get(j);
else if(j==i)
dp[i][j]=dp[i-1][j-1]+triangle.get(i).get(j);
else //该点最短路径=该点值+左上和右上中的最小值
dp[i][j]=triangle.get(i).get(j)+Math.min(dp[i-1][j-1],dp[i-1][j]);
}
}
int min=dp[triangle.size()-1][0];
for(int i=1;i<triangle.size();++i){//找到最小值
if(dp[triangle.size()-1][i]<min)
min=dp[triangle.size()-1][i];
}
return min;
}
}