一.#### 煎饼排序
给你一个整数数组 arr ,请使用 煎饼翻转 完成对数组的排序。
一次煎饼翻转的执行过程如下:
选择一个整数 k ,1 <= k <= arr.length 反转子数组 arr[0...k-1](下标从 0 开始) 例如,arr = [3,2,1,4] ,选择 k = 3 进行一次煎饼翻转,反转子数组 [3,2,1] ,得到 arr = [1,2,3,4] 。
以数组形式返回能使 arr 有序的煎饼翻转操作所对应的 k 值序列。任何将数组排序且翻转次数在 10 * arr.length 范围内的有效答案都将被判断为正确。
**解题思路:**本题就是想把一组数据通过不断翻转指导是从小到大排序位置,本题思路是先找到最大数,将最大数通过索引位置翻转到数组第一个位置,然后再利用最大数翻转到最后,这样就将最大数归位了,次大数依次这样翻转,代码如下:
var pancakeSort = function(arr) {
//记录每个数字的索引
let ind = {};
//记录翻转个数
let ret = [];
//indSort()方法每次更新数字的索引
ind = indSort(arr);
let i = 0
//循环每个数
while(i < arr.length){
//数组最大数就是数组的长度,所以可以找到数组最大数
let max = arr.length - i;
//如果最大数已经在相对应的位置,所以不用翻转,最大数如果是1也不需要翻转了
if(ind[max] !== max - 1 && max > 1 ){
//保存最大数组的索引,翻转maxIndex就将最大数翻转到第一个位置了
let maxIndex = ind[max];
//如果最大索引小于一就没不要翻转了
if(maxIndex > 0){
//因为索引是从0开始的,所以实际翻转个数要加一
ret.push(maxIndex + 1);
//将arr数组进行翻转,翻转maxIndex个
arr = arrSort(arr,maxIndex);
//更新每个数的索引
ind = indSort(arr);
}
//将最大值由第一个翻转到正确位置,如果最大值是1就不需要翻转了
if(max > 1){
//记录翻转位置,就是本身长度
ret.push(max);
//数组翻转
arr = arrSort(arr,max - 1);
//更新索引
ind = indSort(arr);
}
}
//翻转下一个数组
i ++;
}
return ret;
};
//更新数组数字索引
var indSort = function(arr){
let ind = {}
//更新索引
for(let i = 0; i < arr.length; i ++){
ind[arr[i]] = i;
}
return ind;
}
//翻转数组
var arrSort = function(arr,k){
//定义一个空的数组,接受翻转后的数组
let newArr = [];
for(let i = k, j = 0; j < arr.length; i --, j ++){
//i大于0是未反转前的数字
if(i >= 0){
newArr.push(arr[i]);
}else {
//i小于0此时剩下的就是已归位的数字,直接赋值就好了
newArr.push(arr[j]);
}
}
return newArr;
}
二.#### 任务调度器
给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。
然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。
你需要计算完成所有任务所需要的 最短时间 。
**解题思路:**因为相同任务之间要间隔n秒才能执行,所以可以先将最多的任务找出来,先执行最多的任务,其他任务可以从多到少,安排在冷却的位置,可以知道最多任务的时间是:(i(最多任务的个数) - 1) * (n + 1) + i.这个是最多任务的执行时间,如果同时存在多个相同多的任务,后面还要加几个,如果任务的个数大于最多人事执行时间,name最短时间就是总任务长度,代码如下:
var leastInterval = function(tasks, n) {
//记录每个任务的个数
let typeJson = {};
//记录最多任务的名称
let maxText = '';
//统计每个任务的数量
let index = 0;
//开始循环任务
for(let i = 0; i < tasks.length; i ++){
//相同的任务不重复计算
if(!typeJson[tasks[i]]){
//重置新任务数量
index = 1;
//统计相同任务
for(let k = i + 1; k < tasks.length; k ++){
//相同任务index加一
if(tasks[i] === tasks[k]) index ++;
}
//将任务的总数记录到typeJson中
typeJson[tasks[i]] = index;
//找最多任务的名称
if(i < 1){
//默认最多任务是第一个任务
maxText = tasks[i];
}else{
//判断当前任务是否大于maxText,更新最多任务名称
maxText = index > typeJson[maxText] ? tasks[i] : maxText
}
} ;
}
//计算最多任务执行的最少时间,实际还需要加一,实际还需要加一,因为下面for循环是从第一个开始的,所以这里就不加一了,下面会加
let maxLength = (typeJson[maxText] - 1) * (n + 1);
//查找有多少个跟最多任务一样做的任务,如果有就加一,
for(var key in typeJson){
if(typeJson[maxText] === typeJson[key]){
maxLength ++;
}
}
//此时已经计算出最小时间了,判断任务的总长度是否大于最小时间,如果总任务长度大于最小时间就返回任务长度,
if(maxLength < tasks.length) return tasks.length;
return maxLength;
};