768. 最多能完成排序的块 II
初始版本(耗时很长)
//arr[int],有重复元素
//将数组分块,每块排序,再组合
//组合后的结果,和按照升序排序后的原数组相同
//有示例2可以看出,某一位置可以分块的前提是,从该位置分出去的块,该块内包含的元素,与arr数组整体排序之后,对应位置的元素相同也就是[2,1]对应了[1,2],所以可以分成一块
//整体思路:
//先对arr进行升序排序,得到新数组arr1;
//逐个判断该位置处能否分块(难点)
//记录分块位置n,n+1即分块数
//分块判断依据,实质就是从arr和arr1中取出一部分元素,判断其内容是否一致
//(1)确定起点begin和终点end,初始end=begin+1,即保证块内至少有1个元素
//(2)分别取出arr[begin,end]和arr1[begin,end]部分元素,组成新的数组L1和L2(注,此时L1是无序的,L2是有序的)
//(3)对L1进行排序,排序后判断是否与L2完全一致
//(4)若一致,则end后边即使可以分块的位置,令n=n+1;此时更新begin的值,令begin=end,相当于将已经分出去的块舍弃
//(5)若不一致,则令end=end+1,重复执行(1)
//(6)终止条件,当遍历完整个数组arr之后,返回n+1
//注:在判断L1和L2是否一致的操作上,使用排序的话会增加大量运行时间,故使用数组求和是否相等即sum1==sum2来判断更好
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
int begin=0,n=0,end=1;
double sum1=0,sum2=0; //由于题中要求,int型会出现溢出问题
int len=arr.size();
int i;
vector<int> arr1=arr;
sort(arr1.begin(), arr1.end());
while(end<=len) //遍历数组的终止条件
{
cout<<"begin="<<begin<<" end="<<end<<" len="<<len<<endl;
sum1=0;sum2=0;
for(i=begin;i<end;i++) //计算[begin,end)之间的元素的和
{
sum1=sum1+arr[i];
sum2=sum2+arr1[i];
}
cout<<"sum1="<<sum1<<" "<<"sum2="<<sum2<<endl;
if(sum1==sum2)
{
if(end!=len){n++;}
begin=end;
end=begin+1;
}
else
{
end++;
}
cout<<"n="<<n<<endl;
}
return n+1;
}
};
精简后的版本(代码量少,时间提升,空间占用没变)
class Solution {
public:
int maxChunksToSorted(vector<int>& arr) {
int begin=0,n=0;
double sum1=0,sum2=0; //由于题中要求,int型会出现溢出问题
int len=arr.size();
int i;
vector<int> arr1=arr;
sort(arr1.begin(), arr1.end());
while(begin<len) //遍历数组的终止条件
{
sum1=sum1+arr[begin];
sum2=sum2+arr1[begin];
if(sum1==sum2)
{
n++;
sum1=0;sum2=0;
}
begin++;
}
return n;
}
};